home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_xemacs.idb / usr / freeware / lib / xemacs-20.4 / lisp / tm / tm-edit.el.z / tm-edit.el
Encoding:
Text File  |  1998-05-21  |  76.6 KB  |  2,602 lines

  1. ;;; tm-edit.el --- Simple MIME Composer for GNU Emacs
  2.  
  3. ;; Copyright (C) 1993,1994,1995,1996,1997 Free Software Foundation, Inc.
  4.  
  5. ;; Author: UMEDA Masanobu <umerin@mse.kyutech.ac.jp>
  6. ;;         MORIOKA Tomohiko <morioka@jaist.ac.jp>
  7. ;; Maintainer: MORIOKA Tomohiko <morioka@jaist.ac.jp>
  8. ;; Created: 1994/08/21 renamed from mime.el
  9. ;; Version: $Revision: 7.108 $
  10. ;; Keywords: mail, news, MIME, multimedia, multilingual
  11.  
  12. ;; This file is part of tm (Tools for MIME).
  13.  
  14. ;; This program is free software; you can redistribute it and/or
  15. ;; modify it under the terms of the GNU General Public License as
  16. ;; published by the Free Software Foundation; either version 2, or (at
  17. ;; your option) any later version.
  18.  
  19. ;; This program is distributed in the hope that it will be useful, but
  20. ;; WITHOUT ANY WARRANTY; without even the implied warranty of
  21. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  22. ;; General Public License for more details.
  23.  
  24. ;; You should have received a copy of the GNU General Public License
  25. ;; along with GNU Emacs; see the file COPYING.  If not, write to the
  26. ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  27. ;; Boston, MA 02111-1307, USA.
  28.  
  29. ;;; Commentary:
  30.  
  31. ;; This is an Emacs minor mode for editing Internet multimedia
  32. ;; messages formatted in MIME (RFC 2045, 2046, 2047, 2048 and 2049).
  33. ;; All messages in this mode are composed in the tagged MIME format,
  34. ;; that are described in the following examples.  The messages
  35. ;; composed in the tagged MIME format are automatically translated
  36. ;; into a MIME compliant message when exiting the mode.
  37.  
  38. ;; Mule (a multilingual extension to Emacs 18 and 19) has a capability
  39. ;; of handling multilingual text in limited ISO-2022 manner that is
  40. ;; based on early experiences in Japanese Internet community and
  41. ;; resulted in RFC 1468 (ISO-2022-JP charset for MIME).  In order to
  42. ;; enable multilingual capability in single text message in MIME,
  43. ;; charset of multilingual text written in Mule is declared as either
  44. ;; `ISO-2022-JP-2' [RFC 1554].  Mule is required for reading the such
  45. ;; messages.
  46.  
  47. ;; This MIME composer can work with Mail mode, mh-e letter Mode, and
  48. ;; News mode.  First of all, you need the following autoload
  49. ;; definition to load mime/editor-mode automatically:
  50. ;;
  51. ;; (autoload 'mime/editor-mode "tm-edit"
  52. ;;           "Minor mode for editing MIME message." t)
  53. ;;
  54. ;; In case of Mail mode (includes VM mode), you need the following
  55. ;; hook definition:
  56. ;;
  57. ;; (add-hook 'mail-mode-hook 'mime/editor-mode)
  58. ;; (add-hook 'mail-send-hook 'mime-editor/maybe-translate)
  59. ;;
  60. ;; In case of MH-E, you need the following hook definition:
  61. ;;
  62. ;; (add-hook 'mh-letter-mode-hook
  63. ;;           (function
  64. ;;            (lambda ()
  65. ;;              (mime/editor-mode)
  66. ;;              (make-local-variable 'mail-header-separator)
  67. ;;              (setq mail-header-separator "--------")
  68. ;;              ))))
  69. ;; (add-hook 'mh-before-send-letter-hook 'mime-editor/maybe-translate)
  70. ;;
  71. ;; In case of News mode, you need the following hook definition:
  72. ;;
  73. ;; (add-hook 'news-reply-mode-hook 'mime/editor-mode)
  74. ;; (add-hook 'news-inews-hook 'mime-editor/maybe-translate)
  75. ;;
  76. ;; In case of Emacs 19, it is possible to emphasize the message tags
  77. ;; using font-lock mode as follows:
  78. ;;
  79. ;; (add-hook 'mime/editor-mode-hook
  80. ;;           (function
  81. ;;            (lambda ()
  82. ;;              (font-lock-mode 1)
  83. ;;              (setq font-lock-keywords (list mime-editor/tag-regexp))
  84. ;;              ))))
  85.  
  86. ;; The message tag looks like:
  87. ;;
  88. ;;    --[[TYPE/SUBTYPE;PARAMETERS][ENCODING]]
  89. ;;
  90. ;; The tagged MIME message examples:
  91. ;;
  92. ;; This is a conventional plain text.  It should be translated into
  93. ;; text/plain.
  94. ;; 
  95. ;;--[[text/plain]]
  96. ;; This is also a plain text.  But, it is explicitly specified as is.
  97. ;;--[[text/plain; charset=ISO-8859-1]]
  98. ;; This is also a plain text.  But charset is specified as iso-8859-1.
  99. ;;
  100. ;; íHola!  Buenos dφas.  ┐C≤mo estß usted?
  101. ;;--[[text/enriched]]
  102. ;; <center>This is a richtext.</center>
  103. ;;
  104. ;;--[[image/gif][base64]]^M...image encoded in base64 comes here...
  105. ;;
  106. ;;--[[audio/basic][base64]]^M...audio encoded in base64 comes here...
  107.  
  108. ;;; Code:
  109.  
  110. (require 'sendmail)
  111. (require 'mail-utils)
  112. (require 'mel)
  113. (require 'tl-list)
  114. (require 'tm-view)
  115. (require 'tm-ew-e)
  116. (require 'signature)
  117.  
  118.  
  119. ;;; @ version
  120. ;;;
  121.  
  122. (defconst mime-editor/RCS-ID
  123.   "$Id: tm-edit.el,v 7.108 1997/05/27 03:22:55 morioka Exp $")
  124.  
  125. (defconst mime-editor/version (get-version-string mime-editor/RCS-ID))
  126.  
  127. (defconst mime-editor/version-name
  128.   (concat "tm-edit " mime-editor/version))
  129.  
  130.  
  131. ;;; @ variables
  132. ;;;
  133.  
  134. (defvar mime-prefix "\C-c\C-x"
  135.   "*Keymap prefix for MIME commands.")
  136.  
  137. (defvar mime-ignore-preceding-spaces nil
  138.   "*Ignore preceding white spaces if non-nil.")
  139.  
  140. (defvar mime-ignore-trailing-spaces nil
  141.   "*Ignore trailing white spaces if non-nil.")
  142.  
  143. (defvar mime-ignore-same-text-tag t
  144.   "*Ignore preceding text content-type tag that is same with new one.
  145. If non-nil, the text tag is not inserted unless something different.")
  146.  
  147. (defvar mime-auto-hide-body t
  148.   "*Hide non-textual body encoded in base64 after insertion if non-nil.")
  149.  
  150. (defvar mime-editor/voice-recorder
  151.   (function mime-editor/voice-recorder-for-sun)
  152.   "*Function to record a voice message and encode it. [tm-edit.el]")
  153.  
  154. (defvar mime/editor-mode-hook nil
  155.   "*Hook called when enter MIME mode.")
  156.  
  157. (defvar mime-editor/translate-hook nil
  158.   "*Hook called before translating into a MIME compliant message.
  159. To insert a signature file automatically, call the function
  160. `mime-editor/insert-signature' from this hook.")
  161.  
  162. (defvar mime-editor/exit-hook nil
  163.   "*Hook called when exit MIME mode.")
  164.  
  165. (defvar mime-content-types
  166.   '(("text"
  167.      ;; Charset parameter need not to be specified, since it is
  168.      ;; defined automatically while translation.
  169.      ("plain"
  170.       ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
  171.       )
  172.      ("richtext"
  173.       ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
  174.       )
  175.      ("enriched"
  176.       ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
  177.       )
  178.      ("x-latex"
  179.       ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
  180.       )
  181.      ("html"
  182.       ;;("charset" "" "ISO-2022-JP" "US-ASCII" "ISO-8859-1" "ISO-8859-8")
  183.       )
  184.      ("x-rot13-47")
  185.      )
  186.     ("message"
  187.      ("external-body"
  188.       ("access-type"
  189.        ("anon-ftp"
  190.     ("site" "ftp.jaist.ac.jp" "wnoc-fuk.wide.ad.jp" "nic.karrn.ad.jp")
  191.     ("directory" "/pub/GNU/elisp/mime")
  192.     ("name")
  193.     ("mode" "image" "ascii" "local8"))
  194.        ("ftp"
  195.     ("site")
  196.     ("directory")
  197.     ("name")
  198.     ("mode" "image" "ascii" "local8"))
  199.        ("tftp"        ("site") ("name"))
  200.        ("afs"         ("site") ("name"))
  201.        ("local-file"  ("site") ("name"))
  202.        ("mail-server" ("server" "ftpmail@nic.karrn.ad.jp"))
  203.        ))
  204.      ("rfc822")
  205.      )
  206.     ("application"
  207.      ("octet-stream" ("type" "" "tar" "shar"))
  208.      ("postscript")
  209.      ("x-kiss" ("x-cnf")))
  210.     ("image"
  211.      ("gif")
  212.      ("jpeg")
  213.      ("png")
  214.      ("tiff")
  215.      ("x-pic")
  216.      ("x-mag")
  217.      ("x-xwd")
  218.      ("x-xbm")
  219.      )
  220.     ("audio" ("basic"))
  221.     ("video" ("mpeg"))
  222.     )
  223.   "*Alist of content-type, subtype, parameters and its values.")
  224.  
  225. (defvar mime-file-types
  226.   '(("\\.rtf$"
  227.      "text"    "richtext"    nil
  228.      nil
  229.      nil        nil)
  230.     ("\\.html$"
  231.      "text"    "html"        nil
  232.      nil
  233.      nil        nil)
  234.     ("\\.ps$"
  235.      "application" "postscript"    nil
  236.      "quoted-printable"
  237.      "attachment"    (("filename" . file))
  238.      )
  239.     ("\\.jpg$"
  240.      "image"    "jpeg"        nil
  241.      "base64"
  242.      "inline"        (("filename" . file))
  243.      )
  244.     ("\\.gif$"
  245.      "image"    "gif"        nil
  246.      "base64"
  247.      "inline"        (("filename" . file))
  248.      )
  249.     ("\\.png$"
  250.      "image"    "png"        nil
  251.      "base64"
  252.      "inline"        (("filename" . file))
  253.      )
  254.     ("\\.tiff$"
  255.      "image"    "tiff"        nil
  256.      "base64"
  257.      "inline"        (("filename" . file))
  258.      )
  259.     ("\\.pic$"
  260.      "image"    "x-pic"        nil
  261.      "base64"
  262.      "inline"        (("filename" . file))
  263.      )
  264.     ("\\.mag$"
  265.      "image"    "x-mag"        nil
  266.      "base64"
  267.      "inline"        (("filename" . file))
  268.      )
  269.     ("\\.xbm$"
  270.      "image"    "x-xbm"        nil
  271.      "base64"
  272.      "inline"        (("filename" . file))
  273.      )
  274.     ("\\.xwd$"
  275.      "image"    "x-xwd"        nil
  276.      "base64"
  277.      "inline"        (("filename" . file))
  278.      )
  279.     ("\\.au$"
  280.      "audio"    "basic"        nil
  281.      "base64"
  282.      "attachment"        (("filename" . file))
  283.      )
  284.     ("\\.mpg$"
  285.      "video"    "mpeg"        nil
  286.      "base64"
  287.      "attachment"    (("filename" . file))
  288.      )
  289.     ("\\.el$"
  290.      "application" "octet-stream" (("type" . "emacs-lisp"))
  291.      "7bit"
  292.      "attachment"    (("filename" . file))
  293.      )
  294.     ("\\.lsp$"
  295.      "application" "octet-stream" (("type" . "common-lisp"))
  296.      "7bit"
  297.      "attachment"    (("filename" . file))
  298.      )
  299.     ("\\.tar\\.gz$"
  300.      "application" "octet-stream" (("type" . "tar+gzip"))
  301.      "base64"
  302.      "attachment"    (("filename" . file))
  303.      )
  304.     ("\\.tgz$"
  305.      "application" "octet-stream" (("type" . "tar+gzip"))
  306.      "base64"
  307.      "attachment"    (("filename" . file))
  308.      )
  309.     ("\\.tar\\.Z$"
  310.      "application" "octet-stream" (("type" . "tar+compress"))
  311.      "base64"
  312.      "attachment"    (("filename" . file))
  313.      )
  314.     ("\\.taz$"
  315.      "application" "octet-stream" (("type" . "tar+compress"))
  316.      "base64"
  317.      "attachment"    (("filename" . file))
  318.      )
  319.     ("\\.gz$"
  320.      "application" "octet-stream" (("type" . "gzip"))
  321.      "base64"
  322.      "attachment"    (("filename" . file))
  323.      )
  324.     ("\\.Z$"
  325.      "application" "octet-stream" (("type" . "compress"))
  326.      "base64"
  327.      "attachment"    (("filename" . file))
  328.      )
  329.     ("\\.lzh$"
  330.      "application" "octet-stream" (("type" . "lha"))
  331.      "base64"
  332.      "attachment"    (("filename" . file))
  333.      )
  334.     ("\\.zip$"
  335.      "application" "zip" nil
  336.      "base64"
  337.      "attachment"    (("filename" . file))
  338.      )
  339.     ("\\.diff$"
  340.      "application" "octet-stream" (("type" . "patch"))
  341.      nil
  342.      "attachment"    (("filename" . file))
  343.      )
  344.     ("\\.patch$"
  345.      "application" "octet-stream" (("type" . "patch"))
  346.      nil
  347.      "attachment"    (("filename" . file))
  348.      )
  349.     ("\\.signature"
  350.      "text"    "plain"        nil    nil)
  351.     (".*"
  352.      "application" "octet-stream" nil
  353.      nil
  354.      "attachment"    (("filename" . file))
  355.      )
  356.     )
  357.   "*Alist of file name, types, parameters, and default encoding.
  358. If encoding is nil, it is determined from its contents.")
  359.  
  360. ;;; @@ about charset, encoding and transfer-level
  361. ;;;
  362.  
  363. (defvar mime-editor/transfer-level 7
  364.   "*A number of network transfer level.  It should be bigger than 7.")
  365. (make-variable-buffer-local 'mime-editor/transfer-level)
  366.  
  367. (defvar mime-editor/transfer-level-string
  368.   (mime/encoding-name mime-editor/transfer-level 'not-omit)
  369.   "*A string formatted version of mime/defaul-transfer-level")
  370. (make-variable-buffer-local 'mime-editor/transfer-level-string)
  371.  
  372. (defun mime-editor/make-charset-default-encoding-alist (transfer-level)
  373.   (mapcar (function
  374.        (lambda (charset-type)
  375.          (let ((charset  (car charset-type))
  376.            (type     (nth 1 charset-type))
  377.            (encoding (nth 2 charset-type))
  378.            )
  379.            (if (<= type transfer-level)
  380.            (cons charset (mime/encoding-name type))
  381.          (cons charset encoding)
  382.          ))))
  383.       mime-charset-type-list))
  384.  
  385. (defvar mime-editor/charset-default-encoding-alist
  386.   (mime-editor/make-charset-default-encoding-alist mime-editor/transfer-level))
  387. (make-variable-buffer-local 'mime-editor/charset-default-encoding-alist)
  388.  
  389. ;;; @@ about message inserting
  390. ;;;
  391.  
  392. (defvar mime-editor/yank-ignored-field-list
  393.   '("Received" "Approved" "Path" "Replied" "Status"
  394.     "Xref" "X-UIDL" "X-Filter" "X-Gnus-.*" "X-VM-.*")
  395.   "Delete these fields from original message when it is inserted
  396. as message/rfc822 part.
  397. Each elements are regexp of field-name. [tm-edit.el]")
  398.  
  399. (defvar mime-editor/yank-ignored-field-regexp
  400.   (concat "^"
  401.       (apply (function regexp-or) mime-editor/yank-ignored-field-list)
  402.       ":"))
  403.  
  404. (defvar mime-editor/message-inserter-alist nil)
  405. (defvar mime-editor/mail-inserter-alist nil)
  406.  
  407. ;;; @@ about message splitting
  408. ;;;
  409.  
  410. (defvar mime-editor/split-message t
  411.   "*Split large message if it is non-nil. [tm-edit.el]")
  412.  
  413. (defvar mime-editor/message-default-max-lines 1000
  414.   "*Default maximum lines of a message. [tm-edit.el]")
  415.  
  416. (defvar mime-editor/message-max-lines-alist
  417.   '((news-reply-mode . 500))
  418.   "Alist of major-mode vs maximum lines of a message.
  419. If it is not specified for a major-mode,
  420. `mime-editor/message-default-max-lines' is used. [tm-edit.el]")
  421.  
  422. (defconst mime-editor/split-ignored-field-regexp
  423.   "\\(^Content-\\|^Subject:\\|^Mime-Version:\\)")
  424.  
  425. (defvar mime-editor/split-blind-field-regexp
  426.   "\\(^[BDFbdf]cc:\\|^cc:[ \t]*$\\)")
  427.  
  428. (defvar mime-editor/split-message-sender-alist nil)
  429.  
  430. (defvar mime-editor/news-reply-mode-server-running nil)
  431.  
  432.  
  433. ;;; @@ about PGP
  434. ;;;
  435.  
  436. (defvar mime-editor/signing-type 'pgp-elkins
  437.   "*PGP signing type (pgp-elkins, pgp-kazu or nil). [tm-edit.el]")
  438.  
  439. (defvar mime-editor/encrypting-type 'pgp-elkins
  440.   "*PGP encrypting type (pgp-elkins, pgp-kazu or nil). [tm-edit.el]")
  441.  
  442.  
  443. ;;; @@ about tag
  444. ;;;
  445.  
  446. (defconst mime-editor/single-part-tag-regexp
  447.   "--[[][[]\\([^]]*\\)]\\([[]\\([^]]*\\)]\\|\\)]"
  448.   "*Regexp of MIME tag in the form of [[CONTENT-TYPE][ENCODING]].")
  449.  
  450. (defconst mime-editor/quoted-single-part-tag-regexp
  451.   (concat "- " (substring mime-editor/single-part-tag-regexp 1)))
  452.  
  453. (defconst mime-editor/multipart-beginning-regexp "--<<\\([^<>]+\\)>>-{\n")
  454.  
  455. (defconst mime-editor/multipart-end-regexp "--}-<<\\([^<>]+\\)>>\n")
  456.  
  457. (defconst mime-editor/beginning-tag-regexp
  458.   (regexp-or mime-editor/single-part-tag-regexp
  459.          mime-editor/multipart-beginning-regexp))
  460.  
  461. (defconst mime-editor/end-tag-regexp
  462.   (regexp-or mime-editor/single-part-tag-regexp
  463.          mime-editor/multipart-end-regexp))
  464.  
  465. (defconst mime-editor/tag-regexp
  466.   (regexp-or mime-editor/single-part-tag-regexp
  467.          mime-editor/multipart-beginning-regexp
  468.          mime-editor/multipart-end-regexp))
  469.  
  470. (defvar mime-tag-format "--[[%s]]"
  471.   "*Control-string making a MIME tag.")
  472.  
  473. (defvar mime-tag-format-with-encoding "--[[%s][%s]]"
  474.   "*Control-string making a MIME tag with encoding.")
  475.  
  476. ;;; @@ multipart boundary
  477. ;;;
  478.  
  479. (defvar mime-multipart-boundary "Multipart"
  480.   "*Boundary of a multipart message.")
  481.  
  482.  
  483. ;;; @@ buffer local variables
  484. ;;;
  485.  
  486. (defvar mime/editor-mode-old-local-map nil)
  487. (defvar mime/editing-buffer nil)
  488.  
  489.  
  490. ;;; @ constants
  491. ;;;
  492.  
  493. (defconst mime-tspecials-regexp "[][()<>@,;:\\\"/?.= \t]"
  494.   "*Specify MIME tspecials.
  495. Tspecials means any character that matches with it in header must be quoted.")
  496.  
  497. (defconst mime-editor/mime-version-value
  498.   (concat "1.0 (generated by " mime-editor/version-name ")")
  499.   "MIME version number.")
  500.  
  501. (defconst mime-editor/mime-map (make-sparse-keymap)
  502.   "Keymap for MIME commands.")
  503.  
  504. ;;; @ keymap and menu
  505. ;;;
  506.  
  507. (defvar mime/editor-mode-flag nil)
  508. (make-variable-buffer-local 'mime/editor-mode-flag)
  509.  
  510. (defun mime-editor/define-keymap (keymap)
  511.   "Add mime-editor commands to KEYMAP."
  512.   (if (not (keymapp keymap))
  513.       nil
  514.     (define-key keymap "\C-t" 'mime-editor/insert-text)
  515.     (define-key keymap "\C-i" 'mime-editor/insert-file)
  516.     (define-key keymap "\C-e" 'mime-editor/insert-external)
  517.     (define-key keymap "\C-v" 'mime-editor/insert-voice)
  518.     (define-key keymap "\C-y" 'mime-editor/insert-message)
  519.     (define-key keymap "\C-m" 'mime-editor/insert-mail)
  520.     (define-key keymap "\C-w" 'mime-editor/insert-signature)
  521.     (define-key keymap "\C-s" 'mime-editor/insert-signature)
  522.     (define-key keymap "\C-k" 'mime-editor/insert-key)
  523.     (define-key keymap "t"    'mime-editor/insert-tag)
  524.     (define-key keymap "a"    'mime-editor/enclose-alternative-region)
  525.     (define-key keymap "p"    'mime-editor/enclose-parallel-region)
  526.     (define-key keymap "m"    'mime-editor/enclose-mixed-region)
  527.     (define-key keymap "d"    'mime-editor/enclose-digest-region)
  528.     (define-key keymap "s"    'mime-editor/enclose-signed-region)
  529.     (define-key keymap "e"    'mime-editor/enclose-encrypted-region)
  530.     (define-key keymap "q"    'mime-editor/enclose-quote-region)
  531.     (define-key keymap "7"    'mime-editor/set-transfer-level-7bit)
  532.     (define-key keymap "8"    'mime-editor/set-transfer-level-8bit)
  533.     (define-key keymap "/"    'mime-editor/set-split)
  534.     (define-key keymap "v"    'mime-editor/set-sign)
  535.     (define-key keymap "h"    'mime-editor/set-encrypt)
  536.     (define-key keymap "\C-p" 'mime-editor/preview-message)
  537.     (define-key keymap "\C-z" 'mime-editor/exit)
  538.     (define-key keymap "?"    'mime-editor/help)
  539.     ))
  540.  
  541. (mime-editor/define-keymap mime-editor/mime-map)
  542.  
  543. (defun mime-editor/toggle-mode ()
  544.   (interactive)
  545.   (if mime/editor-mode-flag
  546.       (mime-editor/exit 'nomime)
  547.     (mime/editor-mode)
  548.     ))
  549.  
  550. (cond (running-xemacs
  551.        (defconst mime-editor/minor-mime-map nil "Keymap for MIME commands.")
  552.        (or mime-editor/minor-mime-map
  553.        (progn
  554.          (setq mime-editor/minor-mime-map 
  555.            (make-sparse-keymap 'mime-editor/minor-mime-map))
  556.          (define-key
  557.            mime-editor/minor-mime-map mime-prefix mime-editor/mime-map)
  558.          ))
  559.        (add-minor-mode 'mime/editor-mode-flag
  560.                '((" MIME-Edit "  mime-editor/transfer-level-string))
  561.                mime-editor/minor-mime-map
  562.                nil
  563.                'mime-editor/toggle-mode)
  564.        )
  565.       (t
  566.        (set-alist 'minor-mode-alist
  567.           'mime/editor-mode-flag
  568.           '((" MIME-Edit "  mime-editor/transfer-level-string))))
  569.       )
  570.  
  571. (defconst mime-editor/menu-title "MIME-Edit")
  572.  
  573. (defconst mime-editor/menu-list
  574.   '((mime-help    "Describe MIME editor mode" mime-editor/help)
  575.     (file    "Insert File"        mime-editor/insert-file)
  576.     (external    "Insert External"    mime-editor/insert-external)
  577.     (voice    "Insert Voice"        mime-editor/insert-voice)
  578.     (message    "Insert Message"    mime-editor/insert-message)
  579.     (mail    "Insert Mail"        mime-editor/insert-mail)
  580.     (signature    "Insert Signature"    mime-editor/insert-signature)
  581.     (text    "Insert Text"        mime-editor/insert-text)
  582.     (tag    "Insert Tag"        mime-editor/insert-tag)
  583.     (alternative "Enclose as alternative"
  584.          mime-editor/enclose-alternative-region)
  585.     (parallel    "Enclose as parallel"    mime-editor/enclose-parallel-region)
  586.     (mixed    "Enclose as serial"    mime-editor/enclose-mixed-region)
  587.     (digest    "Enclose as digest"    mime-editor/enclose-digest-region)
  588.     (signed    "Enclose as signed"    mime-editor/enclose-signed-region)
  589.     (encrypted    "Enclose as encrypted"    mime-editor/enclose-encrypted-region)
  590.     (quote    "Verbatim region"    mime-editor/enclose-quote-region)
  591.     (key    "Insert Public Key"    mime-editor/insert-key)
  592.     (split    "About split"           mime-editor/set-split)
  593.     (sign    "About sign"        mime-editor/set-sign)
  594.     (encrypt    "About encryption"    mime-editor/set-encrypt)
  595.     (preview    "Preview Message"    mime-editor/preview-message)
  596.     (level    "Toggle transfer-level"    mime-editor/toggle-transfer-level)
  597.     )
  598.   "MIME-edit menubar entry.")
  599.  
  600. (defun mime-editor/define-menu-for-emacs19 ()
  601.   "Define menu for Emacs 19."
  602.   (define-key (current-local-map) [menu-bar mime-edit]
  603.     (cons mime-editor/menu-title
  604.       (make-sparse-keymap mime-editor/menu-title)))
  605.   (mapcar (function
  606.        (lambda (item)
  607.          (define-key (current-local-map)
  608.            (vector 'menu-bar 'mime-edit (car item))
  609.            (cons (nth 1 item)(nth 2 item))
  610.            )
  611.          ))
  612.       (reverse mime-editor/menu-list)
  613.       ))
  614.  
  615. ;;; modified by Pekka Marjola <pema@iki.fi>
  616. ;;;    1995/9/5 (c.f. [tm-en:69])
  617. (defun mime-editor/define-menu-for-xemacs ()
  618.   "Define menu for Emacs 19."
  619.   (cond ((featurep 'menubar)
  620.      (make-local-variable 'current-menubar)
  621.      (set-buffer-menubar current-menubar)
  622.      (add-submenu nil
  623.               (cons mime-editor/menu-title
  624.                 (mapcar (function
  625.                      (lambda (item)
  626.                        (vector (nth 1 item)(nth 2 item)
  627.                            mime/editor-mode-flag)
  628.                        ))
  629.                     mime-editor/menu-list)))
  630.      )))
  631.  
  632. ;;; modified by Steven L. Baur <steve@miranova.com>
  633. ;;;    1995/12/6 (c.f. [tm-en:209])
  634. (if (and running-xemacs (not (boundp 'mime-editor/popup-menu-for-xemacs)))
  635.     (setq mime-editor/popup-menu-for-xemacs
  636.       (append '("MIME Commands" "---")
  637.           (mapcar (function (lambda (item)
  638.                       (vector (nth 1 item)
  639.                           (nth 2 item)
  640.                           t)))
  641.               mime-editor/menu-list)))
  642.   )
  643. ;;; end
  644.  
  645.  
  646. ;;; @ functions
  647. ;;;
  648.  
  649. ;;;###autoload
  650. (defun mime/editor-mode ()
  651.   "MIME minor mode for editing the tagged MIME message.
  652.  
  653. In this mode, basically, the message is composed in the tagged MIME
  654. format. The message tag looks like:
  655.  
  656.     --[[text/plain; charset=ISO-2022-JP][7bit]]
  657.  
  658. The tag specifies the MIME content type, subtype, optional parameters
  659. and transfer encoding of the message following the tag. Messages
  660. without any tag are treated as `text/plain' by default. Charset and
  661. transfer encoding are automatically defined unless explicitly
  662. specified. Binary messages such as audio and image are usually hidden.
  663. The messages in the tagged MIME format are automatically translated
  664. into a MIME compliant message when exiting this mode.
  665.  
  666. Available charsets depend on Emacs version being used. The following
  667. lists the available charsets of each emacs.
  668.  
  669. EMACS 18:    US-ASCII is only available.
  670. NEmacs:        US-ASCII and ISO-2022-JP are available.
  671. EMACS 19:    US-ASCII and ISO-8859-1 (or other charset) are available.
  672. XEmacs 19:    US-ASCII and ISO-8859-1 (or other charset) are available.
  673. Mule:        US-ASCII, ISO-8859-* (except for ISO-8859-5), KOI8-R,
  674.         ISO-2022-JP, ISO-2022-JP-2, ISO-2022-KR, BIG5 and
  675.         ISO-2022-INT-1 are available.
  676.  
  677. ISO-2022-JP-2 and ISO-2022-INT-1 charsets used in mule is expected to
  678. be used to represent multilingual text in intermixed manner. Any
  679. languages that has no registered charset are represented as either
  680. ISO-2022-JP-2 or ISO-2022-INT-1 in mule.
  681.  
  682. If you want to use non-ISO-8859-1 charset in EMACS 19 or XEmacs 19,
  683. please set variable `default-mime-charset'. This variable must be
  684. symbol of which name is a MIME charset.
  685.  
  686. If you want to add more charsets in mule, please set variable
  687. `charsets-mime-charset-alist'. This variable must be alist of which
  688. key is list of leading-char/charset and value is symbol of MIME
  689. charset. (leading-char is a term of MULE 1.* and 2.*. charset is a
  690. term of XEmacs/mule, mule merged EMACS and MULE 3.*) If name of
  691. coding-system is different as MIME charset, please set variable
  692. `mime-charset-coding-system-alist'. This variable must be alist of
  693. which key is MIME charset and value is coding-system.
  694.  
  695. Following commands are available in addition to major mode commands:
  696.  
  697. \[make single part\]
  698. \\[mime-editor/insert-text]    insert a text message.
  699. \\[mime-editor/insert-file]    insert a (binary) file.
  700. \\[mime-editor/insert-external]    insert a reference to external body.
  701. \\[mime-editor/insert-voice]    insert a voice message.
  702. \\[mime-editor/insert-message]    insert a mail or news message.
  703. \\[mime-editor/insert-mail]    insert a mail message.
  704. \\[mime-editor/insert-signature]    insert a signature file at end.
  705. \\[mime-editor/insert-key]    insert PGP public key.
  706. \\[mime-editor/insert-tag]    insert a new MIME tag.
  707.  
  708. \[make enclosure (maybe multipart)\]
  709. \\[mime-editor/enclose-alternative-region]    enclose as multipart/alternative.
  710. \\[mime-editor/enclose-parallel-region]    enclose as multipart/parallel.
  711. \\[mime-editor/enclose-mixed-region]    enclose as multipart/mixed.
  712. \\[mime-editor/enclose-digest-region]    enclose as multipart/digest.
  713. \\[mime-editor/enclose-signed-region]    enclose as PGP signed.
  714. \\[mime-editor/enclose-encrypted-region]    enclose as PGP encrypted.
  715. \\[mime-editor/enclose-quote-region]    enclose as verbose mode (to avoid to expand tags)
  716.  
  717. \[other commands\]
  718. \\[mime-editor/set-transfer-level-7bit]    set transfer-level as 7.
  719. \\[mime-editor/set-transfer-level-8bit]    set transfer-level as 8.
  720. \\[mime-editor/set-split]    set message splitting mode.
  721. \\[mime-editor/set-sign]    set PGP-sign mode.
  722. \\[mime-editor/set-encrypt]    set PGP-encryption mode.
  723. \\[mime-editor/preview-message]    preview editing MIME message.
  724. \\[mime-editor/exit]    exit and translate into a MIME compliant message.
  725. \\[mime-editor/help]    show this help.
  726. \\[mime-editor/maybe-translate]    exit and translate if in MIME mode, then split.
  727.  
  728. Additional commands are available in some major modes:
  729. C-c C-c        exit, translate and run the original command.
  730. C-c C-s        exit, translate and run the original command.
  731.  
  732. The following is a message example written in the tagged MIME format.
  733. TABs at the beginning of the line are not a part of the message:
  734.  
  735.     This is a conventional plain text.  It should be translated
  736.     into text/plain.
  737.     --[[text/plain]]
  738.     This is also a plain text.  But, it is explicitly specified as
  739.     is.
  740.     --[[text/plain; charset=ISO-8859-1]]
  741.     This is also a plain text.  But charset is specified as
  742.     iso-8859-1.
  743.  
  744.     íHola!  Buenos dφas.  ┐C≤mo estß usted?
  745.     --[[text/enriched]]
  746.     This is a <bold>enriched text</bold>.
  747.     --[[image/gif][base64]]...image encoded in base64 here...
  748.     --[[audio/basic][base64]]...audio encoded in base64 here...
  749.  
  750. User customizable variables (not documented all of them):
  751.  mime-prefix
  752.     Specifies a key prefix for MIME minor mode commands.
  753.  
  754.  mime-ignore-preceding-spaces
  755.     Preceding white spaces in a message body are ignored if non-nil.
  756.  
  757.  mime-ignore-trailing-spaces
  758.     Trailing white spaces in a message body are ignored if non-nil.
  759.  
  760.  mime-auto-hide-body
  761.     Hide a non-textual body message encoded in base64 after insertion
  762.     if non-nil.
  763.  
  764.  mime-editor/transfer-level
  765.     A number of network transfer level.  It should be bigger than 7.
  766.     If you are in 8bit-through environment, please set 8.
  767.  
  768.  mime-editor/voice-recorder
  769.     Specifies a function to record a voice message and encode it.
  770.     The function `mime-editor/voice-recorder-for-sun' is for Sun
  771.     SparcStations.
  772.  
  773.  mime/editor-mode-hook
  774.     Turning on MIME mode calls the value of mime/editor-mode-hook, if
  775.     it is non-nil.
  776.  
  777.  mime-editor/translate-hook
  778.     The value of mime-editor/translate-hook is called just before translating
  779.     the tagged MIME format into a MIME compliant message if it is
  780.     non-nil.  If the hook call the function mime-editor/insert-signature,
  781.     the signature file will be inserted automatically.
  782.  
  783.  mime-editor/exit-hook
  784.     Turning off MIME mode calls the value of mime-editor/exit-hook, if it is
  785.     non-nil."
  786.   (interactive)
  787.   (if mime/editor-mode-flag
  788.       (error "You are already editing a MIME message.")
  789.     (setq mime/editor-mode-flag t)
  790.     ;; Remember old key bindings.
  791.     (if running-xemacs
  792.     (use-local-map (or (current-local-map) (make-sparse-keymap)))
  793.       (make-local-variable 'mime/editor-mode-old-local-map)
  794.       (setq mime/editor-mode-old-local-map (current-local-map))
  795.       ;; Add MIME commands to current local map.
  796.       (use-local-map (copy-keymap (or (current-local-map)
  797.                       (make-sparse-keymap))))
  798.       )
  799.     (if (not (lookup-key (current-local-map) mime-prefix))
  800.     (define-key (current-local-map) mime-prefix mime-editor/mime-map))
  801.  
  802.     ;; Set transfer level into mode line
  803.     ;;
  804.     (setq mime-editor/transfer-level-string
  805.        (mime/encoding-name mime-editor/transfer-level 'not-omit))
  806.     (force-mode-line-update)
  807.     
  808.     ;; Define menu.  Menus for other emacs implementations are
  809.     ;; welcome.
  810.     (cond (running-xemacs
  811.        (mime-editor/define-menu-for-xemacs))
  812.       ((>= emacs-major-version 19)
  813.        (mime-editor/define-menu-for-emacs19)
  814.        ))
  815.     ;; end
  816.     
  817.     (enable-invisible)
  818.     
  819.     ;; I don't care about saving these.
  820.     (setq paragraph-start
  821.       (regexp-or mime-editor/single-part-tag-regexp
  822.              paragraph-start))
  823.     (setq paragraph-separate
  824.       (regexp-or mime-editor/single-part-tag-regexp
  825.              paragraph-separate))
  826.     (run-hooks 'mime/editor-mode-hook)
  827.     (message
  828.      (substitute-command-keys
  829.       "Type \\[mime-editor/exit] to exit MIME mode, and type \\[mime-editor/help] to get help."))
  830.     ))
  831.  
  832. ;;;###autoload
  833. (defalias 'edit-mime 'mime/editor-mode)        ; for convenience
  834. (defalias 'mime-mode 'mime/editor-mode)        ; for convenience
  835.  
  836. (defun mime-editor/exit (&optional nomime no-error)
  837.   "Translate the tagged MIME message into a MIME compliant message.
  838. With no argument encode a message in the buffer into MIME, otherwise
  839. just return to previous mode."
  840.   (interactive "P")
  841.   (if (not mime/editor-mode-flag)
  842.       (if (null no-error)
  843.       (error "You aren't editing a MIME message.")
  844.     )
  845.     (if (not nomime)
  846.     (progn
  847.       (run-hooks 'mime-editor/translate-hook)
  848.       (mime-editor/translate-buffer)))
  849.     ;; Restore previous state.
  850.     (setq mime/editor-mode-flag nil)
  851.     (cond (running-xemacs
  852.        (if (featurep 'menubar) 
  853.            (delete-menu-item (list mime-editor/menu-title))))
  854.       (t
  855.        (use-local-map mime/editor-mode-old-local-map)))
  856.     
  857.     (end-of-invisible)
  858.     (set-buffer-modified-p (buffer-modified-p))
  859.     (run-hooks 'mime-editor/exit-hook)
  860.     (message "Exit MIME editor mode.")
  861.     ))
  862.  
  863. (defun mime-editor/maybe-translate ()
  864.   (interactive)
  865.   (mime-editor/exit nil t)
  866.   (call-interactively 'mime-editor/maybe-split-and-send)
  867.   )
  868.  
  869. (defun mime-editor/help ()
  870.   "Show help message about MIME mode."
  871.   (interactive)
  872.   (with-output-to-temp-buffer "*Help*"
  873.     (princ "MIME editor mode:\n")
  874.     (princ (documentation 'mime/editor-mode))
  875.     (print-help-return-message)))
  876.  
  877. (defun mime-editor/insert-text ()
  878.   "Insert a text message.
  879. Charset is automatically obtained from the `charsets-mime-charset-alist'."
  880.   (interactive)
  881.   (let ((ret (mime-editor/insert-tag "text" nil nil)))
  882.   (if ret
  883.       (progn
  884.     (if (looking-at mime-editor/single-part-tag-regexp)
  885.         (progn
  886.           ;; Make a space between the following message.
  887.           (insert "\n")
  888.           (forward-char -1)
  889.           ))
  890.     (if (and (member (second ret) '("enriched" "richtext"))
  891.          (fboundp 'enriched-mode)
  892.          )
  893.         (enriched-mode t)
  894.       (if (boundp 'enriched-mode)
  895.           (enriched-mode nil)
  896.         ))))))
  897.  
  898. (defun mime-editor/insert-file (file &optional verbose)
  899.   "Insert a message from a file."
  900.   (interactive "fInsert file as MIME message: \nP")
  901.   (let*  ((guess (mime-find-file-type file))
  902.       (type (nth 0 guess))
  903.       (subtype (nth 1 guess))
  904.       (parameters (nth 2 guess))
  905.       (encoding (nth 3 guess))
  906.       (disposition-type (nth 4 guess))
  907.       (disposition-params (nth 5 guess))
  908.       )
  909.     (if verbose
  910.     (setq type    (mime-prompt-for-type type)
  911.           subtype (mime-prompt-for-subtype type subtype)
  912.           ))
  913.     (if (or (interactive-p) verbose)
  914.     (setq encoding (mime-prompt-for-encoding encoding))
  915.       )
  916.     (if (or (consp parameters) (stringp disposition-type))
  917.     (let ((rest parameters) cell attribute value)
  918.       (setq parameters "")
  919.       (while rest
  920.         (setq cell (car rest))
  921.         (setq attribute (car cell))
  922.         (setq value (cdr cell))
  923.         (if (eq value 'file)
  924.         (setq value (std11-wrap-as-quoted-string
  925.                  (file-name-nondirectory file)))
  926.           )
  927.         (setq parameters (concat parameters "; " attribute "=" value))
  928.         (setq rest (cdr rest))
  929.         )
  930.       (if disposition-type
  931.           (progn
  932.         (setq parameters
  933.               (concat parameters "\n"
  934.                   "Content-Disposition: " disposition-type))
  935.         (setq rest disposition-params)
  936.         (while rest
  937.           (setq cell (car rest))
  938.           (setq attribute (car cell))
  939.           (setq value (cdr cell))
  940.           (if (eq value 'file)
  941.               (setq value (std11-wrap-as-quoted-string
  942.                    (file-name-nondirectory file)))
  943.             )
  944.           (setq parameters
  945.             (concat parameters "; " attribute "=" value))
  946.           (setq rest (cdr rest))
  947.           )
  948.         ))
  949.       ))
  950.     (mime-editor/insert-tag type subtype parameters)
  951.     (mime-editor/insert-binary-file file encoding)
  952.     ))
  953.  
  954. (defun mime-editor/insert-external ()
  955.   "Insert a reference to external body."
  956.   (interactive)
  957.   (mime-editor/insert-tag "message" "external-body" nil ";\n\t")
  958.   ;;(forward-char -1)
  959.   ;;(insert "Content-Description: " (read-string "Content-Description: ") "\n")
  960.   ;;(forward-line 1)
  961.   (let* ((pritype (mime-prompt-for-type))
  962.      (subtype (mime-prompt-for-subtype pritype))
  963.      (parameters (mime-prompt-for-parameters pritype subtype ";\n\t")))
  964.     (and pritype
  965.      subtype
  966.      (insert "Content-Type: "
  967.          pritype "/" subtype (or parameters "") "\n")))
  968.   (if (and (not (eobp))
  969.        (not (looking-at mime-editor/single-part-tag-regexp)))
  970.       (insert (mime-make-text-tag) "\n")))
  971.  
  972. (defun mime-editor/insert-voice ()
  973.   "Insert a voice message."
  974.   (interactive)
  975.   (let ((encoding
  976.      (completing-read
  977.       "What transfer encoding: "
  978.       mime-file-encoding-method-alist nil t nil)))
  979.     (mime-editor/insert-tag "audio" "basic" nil)
  980.     (mime-editor/define-encoding encoding)
  981.     (save-restriction
  982.       (narrow-to-region (1- (point))(point))
  983.       (unwind-protect
  984.       (funcall mime-editor/voice-recorder encoding)
  985.     (progn
  986.       (insert "\n")
  987.       (invisible-region (point-min)(point-max))
  988.       (goto-char (point-max))
  989.       )))))
  990.  
  991. (defun mime-editor/insert-signature (&optional arg)
  992.   "Insert a signature file."
  993.   (interactive "P")
  994.   (let ((signature-insert-hook
  995.          (function
  996.           (lambda ()
  997.             (apply (function mime-editor/insert-tag)
  998.                    (mime-find-file-type signature-file-name))
  999.             )))
  1000.         )
  1001.     (insert-signature arg)
  1002.     ))
  1003.  
  1004.  
  1005. ;; Insert a new tag around a point.
  1006.  
  1007. (defun mime-editor/insert-tag (&optional pritype subtype parameters delimiter)
  1008.   "Insert new MIME tag and return a list of PRITYPE, SUBTYPE, and PARAMETERS.
  1009. If nothing is inserted, return nil."
  1010.   (interactive)
  1011.   (let ((p (point)))
  1012.     (mime-editor/goto-tag)
  1013.     (if (and (re-search-forward mime-editor/tag-regexp nil t)
  1014.          (< (match-beginning 0) p)
  1015.          (< p (match-end 0))
  1016.          )
  1017.     (goto-char (match-beginning 0))
  1018.       (goto-char p)
  1019.       ))
  1020.   (let ((oldtag nil)
  1021.     (newtag nil)
  1022.     (current (point))
  1023.     )
  1024.     (setq pritype
  1025.       (or pritype
  1026.           (mime-prompt-for-type)))
  1027.     (setq subtype
  1028.       (or subtype
  1029.           (mime-prompt-for-subtype pritype)))
  1030.     (setq parameters
  1031.       (or parameters
  1032.           (mime-prompt-for-parameters pritype subtype delimiter)))
  1033.     ;; Make a new MIME tag.
  1034.     (setq newtag (mime-make-tag pritype subtype parameters))
  1035.     ;; Find an current MIME tag.
  1036.     (setq oldtag
  1037.       (save-excursion
  1038.         (if (mime-editor/goto-tag)
  1039.         (buffer-substring (match-beginning 0) (match-end 0))
  1040.           ;; Assume content type is 'text/plan'.
  1041.           (mime-make-tag "text" "plain")
  1042.           )))
  1043.     ;; We are only interested in TEXT.
  1044.     (if (and oldtag
  1045.          (not (mime-test-content-type
  1046.            (mime-editor/get-contype oldtag) "text")))
  1047.     (setq oldtag nil))
  1048.     ;; Make a new tag.
  1049.     (if (or (not oldtag)        ;Not text
  1050.         (or mime-ignore-same-text-tag
  1051.         (not (string-equal oldtag newtag))))
  1052.     (progn
  1053.       ;; Mark the beginning of the tag for convenience.
  1054.       (push-mark (point) 'nomsg)
  1055.       (insert newtag "\n")
  1056.       (list pritype subtype parameters) ;New tag is created.
  1057.       )
  1058.       ;; Restore previous point.
  1059.       (goto-char current)
  1060.       nil                ;Nothing is created.
  1061.       )
  1062.     ))
  1063.  
  1064. (defun mime-editor/insert-binary-file (file &optional encoding)
  1065.   "Insert binary FILE at point.
  1066. Optional argument ENCODING specifies an encoding method such as base64."
  1067.   (let* ((tagend (1- (point)))        ;End of the tag
  1068.      (hide-p (and mime-auto-hide-body
  1069.               (stringp encoding)
  1070.               (not
  1071.                (let ((en (downcase encoding)))
  1072.              (or (string-equal en "7bit")
  1073.                  (string-equal en "8bit")
  1074.                  (string-equal en "binary")
  1075.                  )))))
  1076.      )
  1077.     (save-restriction
  1078.       (narrow-to-region tagend (point))
  1079.       (mime-insert-encoded-file file encoding)
  1080.       (if hide-p
  1081.       (progn
  1082.         (invisible-region (point-min) (point-max))
  1083.         (goto-char (point-max))
  1084.         )
  1085.     (goto-char (point-max))
  1086.     ))
  1087.     (or hide-p
  1088.     (looking-at mime-editor/tag-regexp)
  1089.     (= (point)(point-max))
  1090.     (mime-editor/insert-tag "text" "plain")
  1091.     )
  1092.     ;; Define encoding even if it is 7bit.
  1093.     (if (stringp encoding)
  1094.     (save-excursion
  1095.       (goto-char tagend) ; Make sure which line the tag is on.
  1096.       (mime-editor/define-encoding encoding)
  1097.       ))
  1098.     ))
  1099.  
  1100.  
  1101. ;; Commands work on a current message flagment.
  1102.  
  1103. (defun mime-editor/goto-tag ()
  1104.   "Search for the beginning of the tagged MIME message."
  1105.   (let ((current (point)) multipart)
  1106.     (if (looking-at mime-editor/tag-regexp)
  1107.     t
  1108.       ;; At first, go to the end.
  1109.       (cond ((re-search-forward mime-editor/beginning-tag-regexp nil t)
  1110.          (goto-char (1- (match-beginning 0))) ;For multiline tag
  1111.          )
  1112.         (t
  1113.          (goto-char (point-max))
  1114.          ))
  1115.       ;; Then search for the beginning. 
  1116.       (re-search-backward mime-editor/end-tag-regexp nil t)
  1117.       (or (looking-at mime-editor/beginning-tag-regexp)
  1118.       ;; Restore previous point.
  1119.       (progn
  1120.         (goto-char current)
  1121.         nil
  1122.         ))
  1123.       )))
  1124.  
  1125. (defun mime-editor/content-beginning ()
  1126.   "Return the point of the beginning of content."
  1127.   (save-excursion
  1128.     (let ((beg (save-excursion
  1129.          (beginning-of-line) (point))))
  1130.       (if (mime-editor/goto-tag)
  1131.       (let ((top (point)))
  1132.         (goto-char (match-end 0))
  1133.         (if (and (= beg top)
  1134.              (= (following-char) ?\^M))
  1135.         (point)
  1136.           (forward-line 1)
  1137.           (point)))
  1138.     ;; Default text/plain tag.
  1139.     (goto-char (point-min))
  1140.     (re-search-forward
  1141.      (concat "\n" (regexp-quote mail-header-separator)
  1142.          (if mime-ignore-preceding-spaces
  1143.              "[ \t\n]*\n" "\n")) nil 'move)
  1144.     (point))
  1145.       )))
  1146.  
  1147. (defun mime-editor/content-end ()
  1148.   "Return the point of the end of content."
  1149.   (save-excursion
  1150.     (let ((beg (point)))
  1151.       (if (mime-editor/goto-tag)
  1152.       (let ((top (point)))
  1153.         (goto-char (match-end 0))
  1154.         (if (invisible-p (point))
  1155.         (next-visible-point (point))
  1156.           ;; Move to the end of this text.
  1157.           (if (re-search-forward mime-editor/tag-regexp nil 'move)
  1158.           ;; Don't forget a multiline tag.
  1159.           (goto-char (match-beginning 0))
  1160.         )
  1161.           (point)
  1162.           ))
  1163.     ;; Assume the message begins with text/plain.
  1164.     (goto-char (mime-editor/content-beginning))
  1165.     (if (re-search-forward mime-editor/tag-regexp nil 'move)
  1166.         ;; Don't forget a multiline tag.
  1167.         (goto-char (match-beginning 0)))
  1168.     (point))
  1169.       )))
  1170.  
  1171. (defun mime-editor/define-charset (charset)
  1172.   "Set charset of current tag to CHARSET."
  1173.   (save-excursion
  1174.     (if (mime-editor/goto-tag)
  1175.     (let ((tag (buffer-substring (match-beginning 0) (match-end 0))))
  1176.       (delete-region (match-beginning 0) (match-end 0))
  1177.       (insert
  1178.        (mime-create-tag
  1179.         (mime-editor/set-parameter
  1180.          (mime-editor/get-contype tag)
  1181.          "charset" (upcase (symbol-name charset)))
  1182.         (mime-editor/get-encoding tag)))
  1183.       ))))
  1184.  
  1185. (defun mime-editor/define-encoding (encoding)
  1186.   "Set encoding of current tag to ENCODING."
  1187.   (save-excursion
  1188.     (if (mime-editor/goto-tag)
  1189.     (let ((tag (buffer-substring (match-beginning 0) (match-end 0))))
  1190.       (delete-region (match-beginning 0) (match-end 0))
  1191.       (insert (mime-create-tag (mime-editor/get-contype tag) encoding)))
  1192.       )))
  1193.  
  1194. (defun mime-editor/choose-charset ()
  1195.   "Choose charset of a text following current point."
  1196.   (detect-mime-charset-region (point) (mime-editor/content-end))
  1197.   )
  1198.  
  1199. (defun mime-make-text-tag (&optional subtype)
  1200.   "Make a tag for a text after current point.
  1201. Subtype of text type can be specified by an optional argument SUBTYPE.
  1202. Otherwise, it is obtained from mime-content-types."
  1203.   (let* ((pritype "text")
  1204.      (subtype (or subtype
  1205.               (car (car (cdr (assoc pritype mime-content-types)))))))
  1206.     ;; Charset should be defined later.
  1207.     (mime-make-tag pritype subtype)))
  1208.  
  1209.  
  1210. ;; Tag handling functions
  1211.  
  1212. (defun mime-make-tag (pritype subtype &optional parameters encoding)
  1213.   "Make a tag of MIME message of PRITYPE, SUBTYPE and optional PARAMETERS."
  1214.   (mime-create-tag (concat (or pritype "") "/" (or subtype "")
  1215.                (or parameters ""))
  1216.            encoding))
  1217.  
  1218. (defun mime-create-tag (contype &optional encoding)
  1219.   "Make a tag with CONTENT-TYPE and optional ENCODING."
  1220.   (format (if encoding mime-tag-format-with-encoding mime-tag-format)
  1221.       contype encoding))
  1222.  
  1223. (defun mime-editor/get-contype (tag)
  1224.   "Return Content-Type (including parameters) of TAG."
  1225.   (and (stringp tag)
  1226.        (or (string-match mime-editor/single-part-tag-regexp tag)
  1227.        (string-match mime-editor/multipart-beginning-regexp tag)
  1228.        (string-match mime-editor/multipart-end-regexp tag)
  1229.        )
  1230.        (substring tag (match-beginning 1) (match-end 1))
  1231.        ))
  1232.  
  1233. (defun mime-editor/get-encoding (tag)
  1234.   "Return encoding of TAG."
  1235.   (and (stringp tag)
  1236.        (string-match mime-editor/single-part-tag-regexp tag)
  1237.        (match-beginning 3)
  1238.        (not (= (match-beginning 3) (match-end 3)))
  1239.        (substring tag (match-beginning 3) (match-end 3))))
  1240.  
  1241. (defun mime-get-parameter (contype parameter)
  1242.   "For given CONTYPE return value for PARAMETER.
  1243. Nil if no such parameter."
  1244.   (if (string-match
  1245.        (concat
  1246.     ";[ \t\n]*"
  1247.     (regexp-quote parameter)
  1248.     "[ \t\n]*=[ \t\n]*\\([^\" \t\n;]*\\|\"[^\"]*\"\\)\\([ \t\n]*;\\|$\\)")
  1249.        contype)
  1250.       (substring contype (match-beginning 1) (match-end 1))
  1251.     nil                    ;No such parameter
  1252.     ))
  1253.  
  1254. (defun mime-editor/set-parameter (contype parameter value)
  1255.   "For given CONTYPE set PARAMETER to VALUE."
  1256.   (let (ctype opt-fields)
  1257.     (if (string-match "\n[^ \t\n\r]+:" contype)
  1258.     (setq ctype (substring contype 0 (match-beginning 0))
  1259.           opt-fields (substring contype (match-beginning 0)))
  1260.       (setq ctype contype)
  1261.       )
  1262.     (if (string-match
  1263.      (concat
  1264.       ";[ \t\n]*\\("
  1265.       (regexp-quote parameter)
  1266.       "[ \t\n]*=[ \t\n]*\\([^\" \t\n;]*\\|\"[^\"]*\"\\)\\)[ \t\n]*\\(;\\|$\\)")
  1267.      ctype)
  1268.     ;; Change value
  1269.     (concat (substring ctype 0 (match-beginning 1))
  1270.         parameter "=" value
  1271.         (substring contype (match-end 1))
  1272.         opt-fields)
  1273.       (concat ctype "; " parameter "=" value opt-fields)
  1274.       )))
  1275.  
  1276. (defun mime-strip-parameters (contype)
  1277.   "Return primary content-type and subtype without parameters for CONTYPE."
  1278.   (if (string-match "^[ \t]*\\([^; \t\n]*\\)" contype)
  1279.       (substring contype (match-beginning 1) (match-end 1)) nil))
  1280.  
  1281. (defun mime-test-content-type (contype type &optional subtype)
  1282.   "Test if CONTYPE is a TYPE and an optional SUBTYPE."
  1283.   (and (stringp contype)
  1284.        (stringp type)
  1285.        (string-match
  1286.     (concat "^[ \t]*" (downcase type) "/" (downcase (or subtype "")))
  1287.     (downcase contype))))
  1288.  
  1289.  
  1290. ;; Basic functions
  1291.  
  1292. (defun mime-find-file-type (file)
  1293.   "Guess Content-Type, subtype, and parameters from FILE."
  1294.   (let ((guess nil)
  1295.     (guesses mime-file-types))
  1296.     (while (and (not guess) guesses)
  1297.       (if (string-match (car (car guesses)) file)
  1298.       (setq guess (cdr (car guesses))))
  1299.       (setq guesses (cdr guesses)))
  1300.     guess
  1301.     ))
  1302.  
  1303. (defun mime-prompt-for-type (&optional default)
  1304.   "Ask for Content-type."
  1305.   (let ((type ""))
  1306.     ;; Repeat until primary content type is specified.
  1307.     (while (string-equal type "")
  1308.       (setq type
  1309.         (completing-read "What content type: "
  1310.                  mime-content-types
  1311.                  nil
  1312.                  'require-match ;Type must be specified.
  1313.                  default
  1314.                  ))
  1315.       (if (string-equal type "")
  1316.       (progn
  1317.         (message "Content type is required.")
  1318.         (beep)
  1319.         (sit-for 1)
  1320.         ))
  1321.       )
  1322.     type))
  1323.  
  1324. (defun mime-prompt-for-subtype (type &optional default)
  1325.   "Ask for subtype of media-type TYPE."
  1326.   (let ((subtypes (cdr (assoc type mime-content-types))))
  1327.     (or (and default
  1328.          (assoc default subtypes))
  1329.     (setq default (car (car subtypes)))
  1330.     ))
  1331.   (let* ((answer
  1332.       (completing-read
  1333.        (if default
  1334.            (concat
  1335.         "What content subtype: (default " default ") ")
  1336.          "What content subtype: ")
  1337.        (cdr (assoc type mime-content-types))
  1338.        nil
  1339.        'require-match        ;Subtype must be specified.
  1340.        nil
  1341.        )))
  1342.     (if (string-equal answer "") default answer)))
  1343.  
  1344. (defun mime-prompt-for-parameters (pritype subtype &optional delimiter)
  1345.   "Ask for Content-type parameters of Content-Type PRITYPE and SUBTYPE.
  1346. Optional DELIMITER specifies parameter delimiter (';' by default)."
  1347.   (let* ((delimiter (or delimiter "; "))
  1348.      (parameters
  1349.       (mapconcat
  1350.        (function identity)
  1351.        (delq nil
  1352.          (mime-prompt-for-parameters-1
  1353.           (cdr (assoc subtype
  1354.                   (cdr (assoc pritype mime-content-types))))))
  1355.        delimiter
  1356.        )))
  1357.     (if (and (stringp parameters)
  1358.          (not (string-equal parameters "")))
  1359.     (concat delimiter parameters)
  1360.       ""                ;"" if no parameters
  1361.       )))
  1362.  
  1363. (defun mime-prompt-for-parameters-1 (optlist)
  1364.   (apply (function append)
  1365.      (mapcar (function mime-prompt-for-parameter) optlist)))
  1366.  
  1367. (defun mime-prompt-for-parameter (parameter)
  1368.   "Ask for PARAMETER.
  1369. Parameter must be '(PROMPT CHOICE1 (CHOISE2 ...))."
  1370.   (let* ((prompt (car parameter))
  1371.      (choices (mapcar (function
  1372.                (lambda (e)
  1373.                  (if (consp e) e (list e))))
  1374.               (cdr parameter)))
  1375.      (default (car (car choices)))
  1376.      (answer nil))
  1377.     (if choices
  1378.     (progn
  1379.       (setq answer
  1380.         (completing-read
  1381.          (concat "What " prompt
  1382.              ": (default "
  1383.              (if (string-equal default "") "\"\"" default)
  1384.              ") ")
  1385.          choices nil nil ""))
  1386.       ;; If nothing is selected, use default.
  1387.       (if (string-equal answer "")
  1388.           (setq answer default)))
  1389.       (setq answer
  1390.         (read-string (concat "What " prompt ": "))))
  1391.     (cons (if (and answer
  1392.            (not (string-equal answer "")))
  1393.           (concat prompt "="
  1394.               ;; Note: control characters ignored!
  1395.               (if (string-match mime-tspecials-regexp answer)
  1396.               (concat "\"" answer "\"") answer)))
  1397.       (mime-prompt-for-parameters-1 (cdr (assoc answer (cdr parameter)))))
  1398.     ))
  1399.  
  1400. (defun mime-prompt-for-encoding (default)
  1401.   "Ask for Content-Transfer-Encoding. [tm-edit.el]"
  1402.   (let (encoding)
  1403.     (while (string=
  1404.         (setq encoding
  1405.           (completing-read
  1406.            "What transfer encoding: "
  1407.            mime-file-encoding-method-alist nil t default)
  1408.           )
  1409.         ""))
  1410.     encoding))
  1411.  
  1412.  
  1413. ;;; @ Translate the tagged MIME messages into a MIME compliant message.
  1414. ;;;
  1415.  
  1416. (defvar mime-editor/translate-buffer-hook
  1417.   '(mime-editor/pgp-enclose-buffer
  1418.     mime-editor/translate-header
  1419.     mime-editor/translate-body))
  1420.  
  1421. (defun mime-editor/translate-header ()
  1422.   "Encode the message header into network representation."
  1423.   (mime/encode-message-header 'code-conversion)
  1424.   (run-hooks 'mime-editor/translate-header-hook)
  1425.   )
  1426.  
  1427. (defun mime-editor/translate-buffer ()
  1428.   "Encode the tagged MIME message in current buffer in MIME compliant message."
  1429.   (interactive)
  1430.   (if (catch 'mime-editor/error
  1431.     (save-excursion
  1432.       (run-hooks 'mime-editor/translate-buffer-hook)
  1433.       ))
  1434.       (progn
  1435.     (undo)
  1436.     (error "Translation error!")
  1437.     )))
  1438.  
  1439. (defun mime-editor/find-inmost ()
  1440.   (goto-char (point-min))
  1441.   (if (re-search-forward mime-editor/multipart-beginning-regexp nil t)
  1442.       (let ((bb (match-beginning 0))
  1443.         (be (match-end 0))
  1444.         (type (buffer-substring (match-beginning 1)(match-end 1)))
  1445.         end-exp eb ee)
  1446.     (setq end-exp (format "--}-<<%s>>\n" type))
  1447.     (widen)
  1448.     (if (re-search-forward end-exp nil t)
  1449.         (progn
  1450.           (setq eb (match-beginning 0))
  1451.           (setq ee (match-end 0))
  1452.           )
  1453.       (setq eb (point-max))
  1454.       (setq ee (point-max))
  1455.       )
  1456.     (narrow-to-region be eb)
  1457.     (goto-char be)
  1458.     (if (re-search-forward mime-editor/multipart-beginning-regexp nil t)
  1459.         (let (ret)
  1460.           (narrow-to-region (match-beginning 0)(point-max))
  1461.           (mime-editor/find-inmost)
  1462.           )
  1463.       (widen)
  1464.       (list type bb be eb)
  1465.       ))))
  1466.  
  1467. (defun mime-editor/process-multipart-1 (boundary)
  1468.   (let ((ret (mime-editor/find-inmost)))
  1469.     (if ret
  1470.     (let ((type (car ret))
  1471.           (bb (nth 1 ret))(be (nth 2 ret))
  1472.           (eb (nth 3 ret))
  1473.           )
  1474.       (narrow-to-region bb eb)
  1475.       (delete-region bb be)
  1476.       (setq bb (point-min))
  1477.       (setq eb (point-max))
  1478.       (widen)
  1479.       (goto-char eb)
  1480.       (if (looking-at mime-editor/multipart-end-regexp)
  1481.           (let ((beg (match-beginning 0))
  1482.             (end (match-end 0))
  1483.             )
  1484.         (delete-region beg end)
  1485.         (or (looking-at mime-editor/beginning-tag-regexp)
  1486.             (eobp)
  1487.             (insert (concat (mime-make-text-tag) "\n"))
  1488.             )))
  1489.       (cond ((string-equal type "quote")
  1490.          (mime-editor/enquote-region bb eb)
  1491.          )
  1492.         ((string-equal type "signed")
  1493.          (cond ((eq mime-editor/signing-type 'pgp-elkins)
  1494.             (mime-editor/sign-pgp-elkins bb eb boundary)
  1495.             )
  1496.                ((eq mime-editor/signing-type 'pgp-kazu)
  1497.             (mime-editor/sign-pgp-kazu bb eb boundary)
  1498.             ))
  1499.          )
  1500.         ((string-equal type "encrypted")
  1501.          (cond ((eq mime-editor/encrypting-type 'pgp-elkins)
  1502.             (mime-editor/encrypt-pgp-elkins bb eb boundary)
  1503.             )
  1504.                ((eq mime-editor/encrypting-type 'pgp-kazu)
  1505.             (mime-editor/encrypt-pgp-kazu bb eb boundary)
  1506.             )))
  1507.         (t
  1508.          (setq boundary
  1509.                (nth 2 (mime-editor/translate-region bb eb
  1510.                                 boundary t)))
  1511.          (goto-char bb)
  1512.          (insert
  1513.           (format "--[[multipart/%s;
  1514.  boundary=\"%s\"][7bit]]\n"
  1515.               type boundary))
  1516.          ))
  1517.       boundary))))
  1518.  
  1519. (defun mime-editor/enquote-region (beg end)
  1520.   (save-excursion
  1521.     (save-restriction
  1522.       (narrow-to-region beg end)
  1523.       (goto-char beg)
  1524.       (while (re-search-forward mime-editor/single-part-tag-regexp nil t)
  1525.     (let ((tag (buffer-substring (match-beginning 0)(match-end 0))))
  1526.       (replace-match (concat "- " (substring tag 1)))
  1527.       )))))
  1528.  
  1529. (defun mime-editor/dequote-region (beg end)
  1530.   (save-excursion
  1531.     (save-restriction
  1532.       (narrow-to-region beg end)
  1533.       (goto-char beg)
  1534.       (while (re-search-forward
  1535.           mime-editor/quoted-single-part-tag-regexp nil t)
  1536.     (let ((tag (buffer-substring (match-beginning 0)(match-end 0))))
  1537.       (replace-match (concat "-" (substring tag 2)))
  1538.       )))))
  1539.  
  1540. (defun mime-editor/sign-pgp-elkins (beg end boundary)
  1541.   (save-excursion
  1542.     (save-restriction
  1543.       (narrow-to-region beg end)
  1544.       (let* ((ret
  1545.           (mime-editor/translate-region beg end boundary))
  1546.          (ctype    (car ret))
  1547.          (encoding (nth 1 ret))
  1548.          (parts    (nth 3 ret))
  1549.          (pgp-boundary (concat "pgp-sign-" boundary))
  1550.          )
  1551.     (goto-char beg)
  1552.     (insert (format "Content-Type: %s\n" ctype))
  1553.     (if encoding
  1554.         (insert (format "Content-Transfer-Encoding: %s\n" encoding))
  1555.       )
  1556.     (insert "\n")
  1557.     (or (as-binary-process
  1558.          (funcall (pgp-function 'mime-sign)
  1559.               (point-min)(point-max) nil nil pgp-boundary))
  1560.         (throw 'mime-editor/error 'pgp-error)
  1561.         )
  1562.     ))))
  1563.  
  1564. (defvar mime-editor/encrypt-recipient-fields-list '("To" "cc"))
  1565.  
  1566. (defun mime-editor/make-encrypt-recipient-header ()
  1567.   (let* ((names mime-editor/encrypt-recipient-fields-list)
  1568.      (values
  1569.       (std11-field-bodies (cons "From" names)
  1570.                   nil mail-header-separator))
  1571.      (from (prog1
  1572.            (car values)
  1573.          (setq values (cdr values))))
  1574.      (header (and (stringp from)
  1575.               (if (string-equal from "")
  1576.               ""
  1577.             (format "From: %s\n" from)
  1578.             )))
  1579.      recipients)
  1580.     (while (and names values)
  1581.       (let ((name (car names))
  1582.         (value (car values))
  1583.         )
  1584.     (and (stringp value)
  1585.          (or (string-equal value "")
  1586.          (progn
  1587.            (setq header (concat header name ": " value "\n")
  1588.              recipients (if recipients
  1589.                     (concat recipients " ," value)
  1590.                       value))
  1591.            ))))
  1592.       (setq names (cdr names)
  1593.         values (cdr values))
  1594.       )
  1595.     (vector from recipients header)
  1596.     ))
  1597.  
  1598. (defun mime-editor/encrypt-pgp-elkins (beg end boundary)
  1599.   (save-excursion
  1600.     (save-restriction
  1601.       (let (from recipients header)
  1602.     (let ((ret (mime-editor/make-encrypt-recipient-header)))
  1603.       (setq from (aref ret 0)
  1604.         recipients (aref ret 1)
  1605.         header (aref ret 2))
  1606.       )
  1607.     (narrow-to-region beg end)
  1608.     (let* ((ret
  1609.         (mime-editor/translate-region beg end boundary))
  1610.            (ctype    (car ret))
  1611.            (encoding (nth 1 ret))
  1612.            (parts    (nth 3 ret))
  1613.            (pgp-boundary (concat "pgp-" boundary))
  1614.            )
  1615.       (goto-char beg)
  1616.       (insert header)
  1617.       (insert (format "Content-Type: %s\n" ctype))
  1618.       (if encoding
  1619.           (insert (format "Content-Transfer-Encoding: %s\n" encoding))
  1620.         )
  1621.       (insert "\n")
  1622.       (or (funcall (pgp-function 'encrypt)
  1623.                recipients (point-min) (point-max) from)
  1624.           (throw 'mime-editor/error 'pgp-error)
  1625.           )
  1626.       (goto-char beg)
  1627.       (insert (format "--[[multipart/encrypted;
  1628.  boundary=\"%s\";
  1629.  protocol=\"application/pgp-encrypted\"][7bit]]
  1630. --%s
  1631. Content-Type: application/pgp-encrypted
  1632.  
  1633. --%s
  1634. Content-Type: application/octet-stream
  1635. Content-Transfer-Encoding: 7bit
  1636.  
  1637. " pgp-boundary pgp-boundary pgp-boundary))
  1638.       (goto-char (point-max))
  1639.       (insert (format "\n--%s--\n" pgp-boundary))
  1640.       )))))
  1641.  
  1642. (defun mime-editor/sign-pgp-kazu (beg end boundary)
  1643.   (save-excursion
  1644.     (save-restriction
  1645.       (narrow-to-region beg end)
  1646.       (let* ((ret
  1647.           (mime-editor/translate-region beg end boundary))
  1648.          (ctype    (car ret))
  1649.          (encoding (nth 1 ret))
  1650.          (parts    (nth 3 ret))
  1651.          )
  1652.     (goto-char beg)
  1653.     (insert (format "Content-Type: %s\n" ctype))
  1654.     (if encoding
  1655.         (insert (format "Content-Transfer-Encoding: %s\n" encoding))
  1656.       )
  1657.     (insert "\n")
  1658.     (or (as-binary-process
  1659.          (funcall (pgp-function 'traditional-sign)
  1660.               beg (point-max)))
  1661.         (throw 'mime-editor/error 'pgp-error)
  1662.         )
  1663.     (goto-char beg)
  1664.     (insert
  1665.      "--[[application/pgp; format=mime][7bit]]\n")
  1666.     ))
  1667.     ))
  1668.  
  1669. (defun mime-editor/encrypt-pgp-kazu (beg end boundary)
  1670.   (save-excursion
  1671.     (let (from recipients header)
  1672.       (let ((ret (mime-editor/make-encrypt-recipient-header)))
  1673.     (setq from (aref ret 0)
  1674.           recipients (aref ret 1)
  1675.           header (aref ret 2))
  1676.     )
  1677.       (save-restriction
  1678.     (narrow-to-region beg end)
  1679.     (let* ((ret
  1680.         (mime-editor/translate-region beg end boundary))
  1681.            (ctype    (car ret))
  1682.            (encoding (nth 1 ret))
  1683.            (parts    (nth 3 ret))
  1684.            )
  1685.       (goto-char beg)
  1686.       (insert header)
  1687.       (insert (format "Content-Type: %s\n" ctype))
  1688.       (if encoding
  1689.           (insert (format "Content-Transfer-Encoding: %s\n" encoding))
  1690.         )
  1691.       (insert "\n")
  1692.       (or (as-binary-process
  1693.            (funcall (pgp-function 'encrypt)
  1694.             recipients beg (point-max) nil 'maybe)
  1695.            )
  1696.           (throw 'mime-editor/error 'pgp-error)
  1697.           )
  1698.       (goto-char beg)
  1699.       (insert
  1700.        "--[[application/pgp; format=mime][7bit]]\n")
  1701.       ))
  1702.       )))
  1703.  
  1704. (defun mime-editor/translate-body ()
  1705.   "Encode the tagged MIME body in current buffer in MIME compliant message."
  1706.   (interactive)
  1707.   (save-excursion
  1708.     (let ((boundary
  1709.        (concat mime-multipart-boundary "_"
  1710.            (replace-space-with-underline (current-time-string))
  1711.            ))
  1712.       (i 1)
  1713.       ret)
  1714.       (while (mime-editor/process-multipart-1
  1715.           (format "%s-%d" boundary i))
  1716.     (setq i (1+ i))
  1717.     )
  1718.       (save-restriction
  1719.     ;; We are interested in message body.
  1720.     (let* ((beg
  1721.         (progn
  1722.           (goto-char (point-min))
  1723.           (re-search-forward
  1724.            (concat "\n" (regexp-quote mail-header-separator)
  1725.                (if mime-ignore-preceding-spaces
  1726.                    "[ \t\n]*\n" "\n")) nil 'move)
  1727.           (point)))
  1728.            (end
  1729.         (progn
  1730.           (goto-char (point-max))
  1731.           (and mime-ignore-trailing-spaces
  1732.                (re-search-backward "[^ \t\n]\n" beg t)
  1733.                (forward-char 1))
  1734.           (point))))
  1735.       (setq ret (mime-editor/translate-region
  1736.              beg end
  1737.              (format "%s-%d" boundary i)))
  1738.       ))
  1739.       (mime-editor/dequote-region (point-min)(point-max))
  1740.       (let ((contype (car ret))        ;Content-Type
  1741.         (encoding (nth 1 ret))    ;Content-Transfer-Encoding
  1742.         )
  1743.     ;; Make primary MIME headers.
  1744.     (or (mail-position-on-field "Mime-Version")
  1745.         (insert mime-editor/mime-version-value))
  1746.     ;; Remove old Content-Type and other fields.
  1747.     (save-restriction
  1748.       (goto-char (point-min))
  1749.       (search-forward (concat "\n" mail-header-separator "\n") nil t)
  1750.       (narrow-to-region (point-min) (point))
  1751.       (goto-char (point-min))
  1752.       (mime-delete-field "Content-Type")
  1753.       (mime-delete-field "Content-Transfer-Encoding"))
  1754.     ;; Then, insert Content-Type and Content-Transfer-Encoding fields.
  1755.     (mail-position-on-field "Content-Type")
  1756.     (insert contype)
  1757.     (if encoding
  1758.         (progn
  1759.           (mail-position-on-field "Content-Transfer-Encoding")
  1760.           (insert encoding)))
  1761.     ))))
  1762.  
  1763. (defun mime-editor/translate-single-part-tag (&optional prefix)
  1764.   (if (re-search-forward mime-editor/single-part-tag-regexp nil t)
  1765.       (let* ((beg (match-beginning 0))
  1766.          (end (match-end 0))
  1767.          (tag (buffer-substring beg end))
  1768.          )
  1769.     (delete-region beg end)
  1770.      (let ((contype (mime-editor/get-contype tag))
  1771.            (encoding (mime-editor/get-encoding tag))
  1772.            )
  1773.       (insert (concat prefix "--" boundary "\n"))
  1774.       (save-restriction
  1775.         (narrow-to-region (point)(point))
  1776.         (insert "Content-Type: " contype "\n")
  1777.         (if encoding
  1778.         (insert "Content-Transfer-Encoding: " encoding "\n"))
  1779.         (mime/encode-message-header)
  1780.         ))
  1781.     t)))
  1782.  
  1783. (defun mime-editor/translate-region (beg end &optional boundary multipart)
  1784.   (if (null boundary)
  1785.       (setq boundary
  1786.         (concat mime-multipart-boundary "_"
  1787.             (replace-space-with-underline (current-time-string))))
  1788.     )
  1789.   (save-excursion
  1790.     (save-restriction
  1791.       (narrow-to-region beg end)
  1792.       (let ((tag nil)            ;MIME tag
  1793.         (contype nil)        ;Content-Type
  1794.         (encoding nil)        ;Content-Transfer-Encoding
  1795.         (nparts 0))            ;Number of body parts
  1796.     ;; Normalize the body part by inserting appropriate message
  1797.     ;; tags for every message contents.
  1798.     (mime-editor/normalize-body)
  1799.     ;; Counting the number of Content-Type.
  1800.     (goto-char (point-min))
  1801.     (while (re-search-forward mime-editor/single-part-tag-regexp nil t)
  1802.       (setq nparts (1+ nparts)))
  1803.     ;; Begin translation.
  1804.     (cond
  1805.      ((and (<= nparts 1)(not multipart))
  1806.       ;; It's a singular message.
  1807.       (goto-char (point-min))
  1808.       (while (re-search-forward
  1809.           mime-editor/single-part-tag-regexp nil t)
  1810.         (setq tag
  1811.           (buffer-substring (match-beginning 0) (match-end 0)))
  1812.         (delete-region (match-beginning 0) (1+ (match-end 0)))
  1813.         (setq contype (mime-editor/get-contype tag))
  1814.         (setq encoding (mime-editor/get-encoding tag))
  1815.         ))
  1816.      (t
  1817.       ;; It's a multipart message.
  1818.       (goto-char (point-min))
  1819.       (and (mime-editor/translate-single-part-tag)
  1820.            (while (mime-editor/translate-single-part-tag "\n"))
  1821.            )
  1822.       ;; Define Content-Type as "multipart/mixed".
  1823.       (setq contype
  1824.         (concat "multipart/mixed;\n boundary=\"" boundary "\""))
  1825.       ;; Content-Transfer-Encoding must be "7bit".
  1826.       ;; The following encoding can be `nil', but is
  1827.       ;; specified as is since there is no way that a user
  1828.       ;; specifies it.
  1829.       (setq encoding "7bit")
  1830.       ;; Insert the trailer.
  1831.       (goto-char (point-max))
  1832.       (insert "\n--" boundary "--\n")
  1833.       ))
  1834.     (list contype encoding boundary nparts)
  1835.     ))))
  1836.  
  1837. (defun mime-editor/normalize-body ()
  1838.   "Normalize the body part by inserting appropriate message tags."
  1839.   ;; Insert the first MIME tags if necessary.
  1840.   (goto-char (point-min))
  1841.   (if (not (looking-at mime-editor/single-part-tag-regexp))
  1842.       (insert (mime-make-text-tag) "\n"))
  1843.   ;; Check each tag, and add new tag or correct it if necessary.
  1844.   (goto-char (point-min))
  1845.   (while (re-search-forward mime-editor/single-part-tag-regexp nil t)
  1846.     (let* ((tag (buffer-substring (match-beginning 0) (match-end 0)))
  1847.        (contype (mime-editor/get-contype tag))
  1848.        (charset (mime-get-parameter contype "charset"))
  1849.        (encoding (mime-editor/get-encoding tag)))
  1850.       ;; Remove extra whitespaces after the tag.
  1851.       (if (looking-at "[ \t]+$")
  1852.       (delete-region (match-beginning 0) (match-end 0)))
  1853.       (let ((beg (point))
  1854.         (end (mime-editor/content-end))
  1855.         )
  1856.     (if (= end (point-max))
  1857.         nil
  1858.       (goto-char end)
  1859.       (or (looking-at mime-editor/beginning-tag-regexp)
  1860.           (eobp)
  1861.           (insert (mime-make-text-tag) "\n")
  1862.           ))
  1863.     (visible-region beg end)
  1864.     (goto-char beg)
  1865.     )
  1866.       (cond
  1867.        ((mime-test-content-type contype "message")
  1868.     ;; Content-type "message" should be sent as is.
  1869.     (forward-line 1)
  1870.     )
  1871.        ((mime-test-content-type contype "text")
  1872.     ;; Define charset for text if necessary.
  1873.     (setq charset (if charset
  1874.               (intern (downcase charset))
  1875.             (mime-editor/choose-charset)))
  1876.     (mime-editor/define-charset charset)
  1877.     (cond ((string-equal contype "text/x-rot13-47")
  1878.            (save-excursion
  1879.          (forward-line)
  1880.          (set-mark (point))
  1881.          (goto-char (mime-editor/content-end))
  1882.          (tm:caesar-region)
  1883.          ))
  1884.           ((string-equal contype "text/enriched")
  1885.            (save-excursion
  1886.          (let ((beg (progn
  1887.                   (forward-line)
  1888.                   (point)))
  1889.                (end (mime-editor/content-end))
  1890.                )
  1891.            ;; Patch for hard newlines
  1892.                    ;; (save-excursion
  1893.                    ;;   (goto-char beg)
  1894.                    ;;   (while (search-forward "\n" end t)
  1895.                    ;;     (put-text-property (match-beginning 0)
  1896.                    ;;                        (point)
  1897.                    ;;                        'hard t)))
  1898.            ;; End patch for hard newlines
  1899.            (enriched-encode beg end)
  1900.            (goto-char beg)
  1901.            (if (search-forward "\n\n")
  1902.                (delete-region beg (match-end 0))
  1903.              )
  1904.            ))))
  1905.     ;; Point is now on current tag.
  1906.     ;; Define encoding and encode text if necessary.
  1907.     (or encoding    ;Encoding is not specified.
  1908.         (let* ((encoding
  1909.             (cdr
  1910.              (assq charset
  1911.                mime-editor/charset-default-encoding-alist)
  1912.              ))
  1913.            (beg (mime-editor/content-beginning))
  1914.            )
  1915.           (encode-mime-charset-region beg (mime-editor/content-end)
  1916.                       charset)
  1917.           (mime-encode-region beg (mime-editor/content-end) encoding)
  1918.           (mime-editor/define-encoding encoding)
  1919.           ))
  1920.     (goto-char (mime-editor/content-end))
  1921.     )
  1922.        ((null encoding)        ;Encoding is not specified.
  1923.     ;; Application, image, audio, video, and any other
  1924.     ;; unknown content-type without encoding should be
  1925.     ;; encoded.
  1926.     (let* ((encoding "base64")    ;Encode in BASE64 by default.
  1927.            (beg (mime-editor/content-beginning))
  1928.            (end (mime-editor/content-end))
  1929.            (body (buffer-substring beg end))
  1930.            )
  1931.       (mime-encode-region beg end encoding)
  1932.       (mime-editor/define-encoding encoding))
  1933.     (forward-line 1)
  1934.     ))
  1935.       )))
  1936.  
  1937. (defun mime-delete-field (field)
  1938.   "Delete header FIELD."
  1939.   (let ((regexp (format "^%s:[ \t]*" field)))
  1940.     (goto-char (point-min))
  1941.     (while (re-search-forward regexp nil t)
  1942.       (delete-region (match-beginning 0)
  1943.              (progn (forward-line 1) (point)))
  1944.       )))
  1945.  
  1946.  
  1947. ;;;
  1948. ;;; Platform dependent functions
  1949. ;;;
  1950.  
  1951. ;; Sun implementations
  1952.  
  1953. (defun mime-editor/voice-recorder-for-sun (encoding)
  1954.   "Record voice in a buffer using Sun audio device,
  1955. and insert data encoded as ENCODING. [tm-edit.el]"
  1956.   (message "Start the recording on %s.  Type C-g to finish the recording..."
  1957.        (system-name))
  1958.   (mime-insert-encoded-file "/dev/audio" encoding)
  1959.   )
  1960.  
  1961.  
  1962. ;;; @ Other useful commands.
  1963. ;;;
  1964.  
  1965. ;; Message forwarding commands as content-type "message/rfc822".
  1966.  
  1967. (defun mime-editor/insert-message (&optional message)
  1968.   (interactive)
  1969.   (let ((inserter (assoc-value major-mode mime-editor/message-inserter-alist)))
  1970.     (if (and inserter (fboundp inserter))
  1971.     (progn
  1972.       (mime-editor/insert-tag "message" "rfc822")
  1973.       (funcall inserter message)
  1974.       )
  1975.       (message "Sorry, I don't have message inserter for your MUA.")
  1976.       )))
  1977.  
  1978. (defun mime-editor/insert-mail (&optional message)
  1979.   (interactive)
  1980.   (let ((inserter (assoc-value major-mode mime-editor/mail-inserter-alist)))
  1981.     (if (and inserter (fboundp inserter))
  1982.     (progn
  1983.       (mime-editor/insert-tag "message" "rfc822")
  1984.       (funcall inserter message)
  1985.       )
  1986.       (message "Sorry, I don't have mail inserter for your MUA.")
  1987.       )))
  1988.  
  1989. (defun mime-editor/inserted-message-filter ()
  1990.   (save-excursion
  1991.     (save-restriction
  1992.       (let ((header-start (point))
  1993.         (case-fold-search t)
  1994.         beg end)
  1995.     ;; for Emacs 18
  1996.     ;; (if (re-search-forward "^$" (marker-position (mark-marker)))
  1997.     (if (re-search-forward "^$" (mark t))
  1998.         (narrow-to-region header-start (match-beginning 0))
  1999.       )
  2000.     (goto-char header-start)
  2001.     (while (and (re-search-forward
  2002.              mime-editor/yank-ignored-field-regexp nil t)
  2003.             (setq beg (match-beginning 0))
  2004.             (setq end (1+ (std11-field-end)))
  2005.             )
  2006.       (delete-region beg end)
  2007.       )
  2008.     ))))
  2009.  
  2010.  
  2011. ;;; @ multipart enclosure
  2012. ;;;
  2013.  
  2014. (defun mime-editor/enclose-region (type beg end)
  2015.   (save-excursion
  2016.     (goto-char beg)
  2017.     (let ((current (point)))
  2018.       (save-restriction
  2019.     (narrow-to-region beg end)
  2020.     (insert (format "--<<%s>>-{\n" type))
  2021.     (goto-char (point-max))
  2022.     (insert (format "--}-<<%s>>\n" type))
  2023.     (goto-char (point-max))
  2024.     )
  2025.       (or (looking-at mime-editor/beginning-tag-regexp)
  2026.       (eobp)
  2027.       (insert (mime-make-text-tag) "\n")
  2028.       )
  2029.       )))
  2030.  
  2031. (defun mime-editor/enclose-quote-region (beg end)
  2032.   (interactive "*r")
  2033.   (mime-editor/enclose-region "quote" beg end)
  2034.   )
  2035.  
  2036. (defun mime-editor/enclose-mixed-region (beg end)
  2037.   (interactive "*r")
  2038.   (mime-editor/enclose-region "mixed" beg end)
  2039.   )
  2040.  
  2041. (defun mime-editor/enclose-parallel-region (beg end)
  2042.   (interactive "*r")
  2043.   (mime-editor/enclose-region "parallel" beg end)
  2044.   )
  2045.  
  2046. (defun mime-editor/enclose-digest-region (beg end)
  2047.   (interactive "*r")
  2048.   (mime-editor/enclose-region "digest" beg end)
  2049.   )
  2050.  
  2051. (defun mime-editor/enclose-alternative-region (beg end)
  2052.   (interactive "*r")
  2053.   (mime-editor/enclose-region "alternative" beg end)
  2054.   )
  2055.  
  2056. (defun mime-editor/enclose-signed-region (beg end)
  2057.   (interactive "*r")
  2058.   (if mime-editor/signing-type
  2059.       (mime-editor/enclose-region "signed" beg end)
  2060.     (message "Please specify signing type.")
  2061.     ))
  2062.  
  2063. (defun mime-editor/enclose-encrypted-region (beg end)
  2064.   (interactive "*r")
  2065.   (if mime-editor/signing-type
  2066.       (mime-editor/enclose-region "encrypted" beg end)
  2067.     (message "Please specify encrypting type.")
  2068.     ))
  2069.  
  2070. (defun mime-editor/insert-key (&optional arg)
  2071.   "Insert a pgp public key."
  2072.   (interactive "P")
  2073.   (mime-editor/insert-tag "application" "pgp-keys")
  2074.   (mime-editor/define-encoding "7bit")
  2075.   (funcall (pgp-function 'insert-key))
  2076.   )
  2077.  
  2078.  
  2079. ;;; @ flag setting
  2080. ;;;
  2081.  
  2082. (defun mime-editor/set-split (arg)
  2083.   (interactive
  2084.    (list
  2085.     (y-or-n-p "Do you want to enable split?")
  2086.     ))
  2087.   (setq mime-editor/split-message arg)
  2088.   (if arg
  2089.       (message "This message is enabled to split.")
  2090.     (message "This message is not enabled to split.")
  2091.     ))
  2092.  
  2093. (defun mime-editor/toggle-transfer-level (&optional transfer-level)
  2094.   "Toggle transfer-level is 7bit or 8bit through.
  2095.  
  2096. Optional TRANSFER-LEVEL is a number of transfer-level, 7 or 8."
  2097.   (interactive)
  2098.   (if (numberp transfer-level)
  2099.       (setq mime-editor/transfer-level transfer-level)
  2100.     (if (< mime-editor/transfer-level 8)
  2101.     (setq mime-editor/transfer-level 8)
  2102.       (setq mime-editor/transfer-level 7)
  2103.       ))
  2104.   (setq mime-editor/charset-default-encoding-alist
  2105.     (mime-editor/make-charset-default-encoding-alist
  2106.      mime-editor/transfer-level))
  2107.   (message (format "Current transfer-level is %d bit"
  2108.            mime-editor/transfer-level))
  2109.   (setq mime-editor/transfer-level-string
  2110.     (mime/encoding-name mime-editor/transfer-level 'not-omit))
  2111.   (force-mode-line-update)
  2112.   )
  2113.  
  2114. (defun mime-editor/set-transfer-level-7bit ()
  2115.   (interactive)
  2116.   (mime-editor/toggle-transfer-level 7)
  2117.   )
  2118.  
  2119. (defun mime-editor/set-transfer-level-8bit ()
  2120.   (interactive)
  2121.   (mime-editor/toggle-transfer-level 8)
  2122.   )
  2123.  
  2124.  
  2125. ;;; @ pgp
  2126. ;;;
  2127.  
  2128. (defun mime-editor/set-sign (arg)
  2129.   (interactive
  2130.    (list
  2131.     (y-or-n-p "Do you want to sign?")
  2132.     ))
  2133.   (if arg
  2134.       (if mime-editor/signing-type
  2135.       (progn
  2136.         (setq mime-editor/pgp-processing 'sign)
  2137.         (message "This message will be signed.")
  2138.         )
  2139.     (message "Please specify signing type.")
  2140.     )
  2141.     (if (eq mime-editor/pgp-processing 'sign)
  2142.     (setq mime-editor/pgp-processing nil)
  2143.       )
  2144.     (message "This message will not be signed.")
  2145.     ))
  2146.  
  2147. (defun mime-editor/set-encrypt (arg)
  2148.   (interactive
  2149.    (list
  2150.     (y-or-n-p "Do you want to encrypt?")
  2151.     ))
  2152.   (if arg
  2153.       (if mime-editor/encrypting-type
  2154.       (progn
  2155.         (setq mime-editor/pgp-processing 'encrypt)
  2156.         (message "This message will be encrypt.")
  2157.         )
  2158.     (message "Please specify encrypting type.")
  2159.     )
  2160.     (if (eq mime-editor/pgp-processing 'encrypt)
  2161.     (setq mime-editor/pgp-processing nil)
  2162.       )
  2163.     (message "This message will not be encrypt.")
  2164.     ))
  2165.  
  2166. (defvar mime-editor/pgp-processing nil)
  2167. (make-variable-buffer-local 'mime-editor/pgp-processing)
  2168.  
  2169. (defun mime-editor/pgp-enclose-buffer ()
  2170.   (let ((beg (save-excursion
  2171.            (goto-char (point-min))
  2172.            (if (search-forward (concat "\n" mail-header-separator "\n"))
  2173.            (match-end 0)
  2174.          )))
  2175.     (end (point-max))
  2176.     )
  2177.     (if beg
  2178.     (cond ((eq mime-editor/pgp-processing 'sign)
  2179.            (mime-editor/enclose-signed-region beg end)
  2180.            )
  2181.           ((eq mime-editor/pgp-processing 'encrypt)
  2182.            (mime-editor/enclose-encrypted-region beg end)
  2183.            ))
  2184.       )))
  2185.  
  2186.  
  2187. ;;; @ split
  2188. ;;;
  2189.  
  2190. (defun mime-editor/insert-partial-header
  2191.   (fields subject id number total separator)
  2192.   (insert fields)
  2193.   (insert (format "Subject: %s (%d/%d)\n" subject number total))
  2194.   (insert (format "Mime-Version: 1.0 (split by %s)\n"
  2195.           mime-editor/version-name))
  2196.   (insert (format "\
  2197. Content-Type: message/partial; id=%s; number=%d; total=%d\n%s\n"
  2198.           id number total separator))
  2199.   )
  2200.  
  2201. (defun mime-editor/split-and-send
  2202.   (&optional cmd lines mime-editor/message-max-length)
  2203.   (interactive)
  2204.   (or lines
  2205.       (setq lines
  2206.         (count-lines (point-min) (point-max)))
  2207.       )
  2208.   (or mime-editor/message-max-length
  2209.       (setq mime-editor/message-max-length
  2210.         (or (cdr (assq major-mode mime-editor/message-max-lines-alist))
  2211.         mime-editor/message-default-max-lines))
  2212.       )
  2213.   (let* ((mime-editor/draft-file-name 
  2214.       (or (buffer-file-name)
  2215.           (make-temp-name
  2216.            (expand-file-name "tm-draft" mime/tmp-dir))))
  2217.      (separator mail-header-separator)
  2218.      (id (concat "\""
  2219.              (replace-space-with-underline (current-time-string))
  2220.              "@" (system-name) "\"")))
  2221.     (run-hooks 'mime-editor/before-split-hook)
  2222.     (let ((the-buf (current-buffer))
  2223.       (copy-buf (get-buffer-create " *Original Message*"))
  2224.       (header (std11-header-string-except
  2225.            mime-editor/split-ignored-field-regexp separator))
  2226.       (subject (mail-fetch-field "subject"))
  2227.       (total (+ (/ lines mime-editor/message-max-length)
  2228.             (if (> (mod lines mime-editor/message-max-length) 0)
  2229.             1)))
  2230.       (command
  2231.        (or cmd
  2232.            (cdr
  2233.         (assq major-mode
  2234.               mime-editor/split-message-sender-alist))
  2235.            (function
  2236.         (lambda ()
  2237.           (interactive)
  2238.           (error "Split sender is not specified for `%s'." major-mode)
  2239.           ))
  2240.            ))
  2241.       (mime-editor/partial-number 1)
  2242.       data)
  2243.       (save-excursion
  2244.     (set-buffer copy-buf)
  2245.     (erase-buffer)
  2246.     (insert-buffer the-buf)
  2247.     (save-restriction
  2248.       (if (re-search-forward
  2249.            (concat "^" (regexp-quote separator) "$") nil t)
  2250.           (let ((he (match-beginning 0)))
  2251.         (replace-match "")
  2252.         (narrow-to-region (point-min) he)
  2253.         ))
  2254.       (goto-char (point-min))
  2255.       (while (re-search-forward mime-editor/split-blind-field-regexp nil t)
  2256.         (delete-region (match-beginning 0)
  2257.                (1+ (std11-field-end)))
  2258.         )))
  2259.       (while (< mime-editor/partial-number total)
  2260.     (erase-buffer)
  2261.     (save-excursion
  2262.       (set-buffer copy-buf)
  2263.       (setq data (buffer-substring
  2264.               (point-min)
  2265.               (progn
  2266.             (goto-line mime-editor/message-max-length)
  2267.             (point))
  2268.               ))
  2269.       (delete-region (point-min)(point))
  2270.       )
  2271.     (mime-editor/insert-partial-header
  2272.      header subject id mime-editor/partial-number total separator)
  2273.     (insert data)
  2274.     (save-excursion
  2275.       (message (format "Sending %d/%d..."
  2276.                mime-editor/partial-number total))
  2277.       (call-interactively command)
  2278.       (message (format "Sending %d/%d... done"
  2279.                mime-editor/partial-number total))
  2280.       )
  2281.     (setq mime-editor/partial-number
  2282.           (1+ mime-editor/partial-number))
  2283.     )
  2284.       (erase-buffer)
  2285.       (save-excursion
  2286.     (set-buffer copy-buf)
  2287.     (setq data (buffer-string))
  2288.     (erase-buffer)
  2289.     )
  2290.       (mime-editor/insert-partial-header
  2291.        header subject id mime-editor/partial-number total separator)
  2292.       (insert data)
  2293.       (save-excursion
  2294.     (message (format "Sending %d/%d..."
  2295.              mime-editor/partial-number total))
  2296.     (message (format "Sending %d/%d... done"
  2297.              mime-editor/partial-number total))
  2298.     )
  2299.       )))
  2300.  
  2301. (defun mime-editor/maybe-split-and-send (&optional cmd)
  2302.   (interactive)
  2303.   (run-hooks 'mime-editor/before-send-hook)
  2304.   (let ((mime-editor/message-max-length
  2305.      (or (cdr (assq major-mode mime-editor/message-max-lines-alist))
  2306.          mime-editor/message-default-max-lines))
  2307.     (lines (count-lines (point-min) (point-max)))
  2308.     )
  2309.     (if (and (> lines mime-editor/message-max-length)
  2310.          mime-editor/split-message)
  2311.     (mime-editor/split-and-send cmd lines mime-editor/message-max-length)
  2312.       )))
  2313.  
  2314.  
  2315. ;;; @ preview message
  2316. ;;;
  2317.  
  2318. (defun mime-editor/preview-message ()
  2319.   "preview editing MIME message. [tm-edit.el]"
  2320.   (interactive)
  2321.   (let* ((str (buffer-string))
  2322.      (separator mail-header-separator)
  2323.      (the-buf (current-buffer))
  2324.      (buf-name (buffer-name))
  2325.      (temp-buf-name (concat "*temp-article:" buf-name "*"))
  2326.      (buf (get-buffer temp-buf-name))
  2327.      )
  2328.     (if buf
  2329.     (progn
  2330.       (switch-to-buffer buf)
  2331.       (erase-buffer)
  2332.       )
  2333.       (setq buf (get-buffer-create temp-buf-name))
  2334.       (switch-to-buffer buf)
  2335.       )
  2336.     (insert str)
  2337.     (setq major-mode 'mime/temporary-message-mode)
  2338.     (make-local-variable 'mail-header-separator)
  2339.     (setq mail-header-separator separator)
  2340.     (make-local-variable 'mime/editing-buffer)
  2341.     (setq mime/editing-buffer the-buf)
  2342.     
  2343.     (run-hooks 'mime-editor/translate-hook)
  2344.     (mime-editor/translate-buffer)
  2345.     (goto-char (point-min))
  2346.     (if (re-search-forward
  2347.      (concat "^" (regexp-quote separator) "$"))
  2348.     (replace-match "")
  2349.       )
  2350.     (mime/viewer-mode)
  2351.     ))
  2352.  
  2353. (defun mime-editor/quitting-method ()
  2354.   (let ((temp mime::preview/article-buffer)
  2355.     buf)
  2356.     (mime-viewer/kill-buffer)
  2357.     (set-buffer temp)
  2358.     (setq buf mime/editing-buffer)
  2359.     (kill-buffer temp)
  2360.     (switch-to-buffer buf)
  2361.     ))
  2362.  
  2363. (set-alist 'mime-viewer/quitting-method-alist
  2364.        'mime/temporary-message-mode
  2365.        (function mime-editor/quitting-method)
  2366.        )
  2367.  
  2368.  
  2369. ;;; @ draft preview
  2370. ;;; 
  2371. ;; by "OKABE Yasuo <okabe@kudpc.kyoto-u.ac.jp>
  2372. ;;     Mon, 10 Apr 1995 20:03:07 +0900
  2373.  
  2374. (defvar mime-editor/draft-header-separator-alist
  2375.   '((news-reply-mode . mail-header-separator)
  2376.     (mh-letter-mode . mail-header-separator)
  2377.     ))
  2378.  
  2379. (defvar mime::article/draft-header-separator nil)
  2380.  
  2381. (defun mime-editor/draft-preview ()
  2382.   (interactive)
  2383.   (let ((sep (cdr (assq major-mode mime-editor/draft-header-separator-alist))))
  2384.     (or (stringp sep) (setq sep (eval sep)))
  2385.     (make-variable-buffer-local 'mime::article/draft-header-separator)
  2386.     (goto-char (point-min))
  2387.     (re-search-forward
  2388.      (concat "^\\(" (regexp-quote sep) "\\)?$"))
  2389.     (setq mime::article/draft-header-separator
  2390.       (buffer-substring (match-beginning 0) (match-end 0)))
  2391.     (replace-match "")
  2392.     (mime/viewer-mode (current-buffer))
  2393.     (pop-to-buffer (current-buffer))
  2394.     ))
  2395.  
  2396. (defun mime-viewer::quitting-method/draft-preview ()
  2397.   (let ((mother mime::preview/mother-buffer))
  2398.     (save-excursion
  2399.       (switch-to-buffer mother)
  2400.       (goto-char (point-min))
  2401.       (if (and
  2402.        (re-search-forward
  2403.         (concat "^\\("
  2404.             (regexp-quote mime::article/draft-header-separator)
  2405.             "\\)?$") nil t)
  2406.        (bolp))
  2407.       (progn
  2408.         (insert mime::article/draft-header-separator)
  2409.         (set-buffer-modified-p (buffer-modified-p))
  2410.         )))
  2411.     (mime-viewer/kill-buffer)
  2412.     (pop-to-buffer mother)
  2413.     ))
  2414.  
  2415. (set-alist 'mime-viewer/quitting-method-alist
  2416.        'mh-letter-mode
  2417.        (function mime-viewer::quitting-method/draft-preview)
  2418.        )
  2419.  
  2420. (set-alist 'mime-viewer/quitting-method-alist
  2421.        'news-reply-mode
  2422.        (function mime-viewer::quitting-method/draft-preview)
  2423.        )
  2424.  
  2425.  
  2426. ;;; @ edit again
  2427. ;;;
  2428.  
  2429. (defun mime-editor::edit-again (code-conversion)
  2430.   (save-excursion
  2431.     (goto-char (point-min))
  2432.     (let ((ctl (mime/Content-Type)))
  2433.       (if ctl
  2434.       (let ((ctype (car ctl))
  2435.         (params (cdr ctl))
  2436.         type stype)
  2437.         (if (string-match "/" ctype)
  2438.         (progn
  2439.           (setq type (substring ctype 0 (match-beginning 0)))
  2440.           (setq stype (substring ctype (match-end 0)))
  2441.           )
  2442.           (setq type ctype)
  2443.           )
  2444.         (cond
  2445.          ((string= ctype "application/pgp-signature")
  2446.           (delete-region (point-min)(point-max))
  2447.           )
  2448.          ((string= type "multipart")
  2449.           (let* ((boundary (assoc-value "boundary" params))
  2450.              (boundary-pat
  2451.               (concat "\n--" (regexp-quote boundary) "[ \t]*\n"))
  2452.              )
  2453.         (re-search-forward boundary-pat nil t)
  2454.         (let ((bb (match-beginning 0)) eb tag)
  2455.           (setq tag (format "\n--<<%s>>-{\n" stype))
  2456.           (goto-char bb)
  2457.           (insert tag)
  2458.           (setq bb (+ bb (length tag)))
  2459.           (re-search-forward
  2460.            (concat "\n--" (regexp-quote boundary) "--[ \t]*\n")
  2461.            nil t)
  2462.           (setq eb (match-beginning 0))
  2463.           (replace-match (format "--}-<<%s>>\n" stype))
  2464.           (save-restriction
  2465.             (narrow-to-region bb eb)
  2466.             (goto-char (point-min))
  2467.             (while (re-search-forward boundary-pat nil t)
  2468.               (let ((beg (match-beginning 0))
  2469.                 end)
  2470.             (delete-region beg (match-end 0))
  2471.             (save-excursion
  2472.               (if (re-search-forward boundary-pat nil t)
  2473.                   (setq end (match-beginning 0))
  2474.                 (setq end (point-max))
  2475.                 )
  2476.               (save-restriction
  2477.                 (narrow-to-region beg end)
  2478.                 (mime-editor::edit-again code-conversion)
  2479.                 (goto-char (point-max))
  2480.                 ))))
  2481.             ))
  2482.         (goto-char (point-min))
  2483.         (or (= (point-min) 1)
  2484.             (delete-region (point-min)
  2485.                    (if (search-forward "\n\n" nil t)
  2486.                        (match-end 0)
  2487.                      (point-min)
  2488.                      )))
  2489.         ))
  2490.          (t
  2491.           (let* (charset
  2492.              (pstr
  2493.               (let ((bytes (+ 14 (length ctype))))
  2494.             (mapconcat (function
  2495.                     (lambda (attr)
  2496.                       (if (string-equal (car attr) "charset")
  2497.                       (progn
  2498.                         (setq charset (cdr attr))
  2499.                         "")
  2500.                     (let* ((str
  2501.                         (concat (car attr)
  2502.                             "=" (cdr attr))
  2503.                         )
  2504.                            (bs (length str))
  2505.                            )
  2506.                       (setq bytes (+ bytes bs 2))
  2507.                       (if (< bytes 76)
  2508.                           (concat "; " str)
  2509.                         (setq bytes (+ bs 1))
  2510.                         (concat ";\n " str)
  2511.                         )
  2512.                       ))))
  2513.                    params "")))
  2514.              encoding
  2515.              encoded)
  2516.         (save-excursion
  2517.           (if (re-search-forward
  2518.                "Content-Transfer-Encoding:" nil t)
  2519.               (let ((beg (match-beginning 0))
  2520.                 (hbeg (match-end 0))
  2521.                 (end (std11-field-end)))
  2522.             (setq encoding
  2523.                   (eliminate-top-spaces
  2524.                    (std11-unfold-string
  2525.                 (buffer-substring hbeg end))))
  2526.             (if (or charset (string-equal type "text"))
  2527.                 (progn
  2528.                   (delete-region beg (1+ end))
  2529.                   (goto-char (point-min))
  2530.                   (if (search-forward "\n\n" nil t)
  2531.                   (progn
  2532.                     (mime-decode-region
  2533.                      (match-end 0)(point-max) encoding)
  2534.                     (setq encoded t
  2535.                       encoding nil)
  2536.                     )))))))
  2537.         (if (or code-conversion encoded)
  2538.             (decode-mime-charset-region
  2539.              (point-min)(point-max)
  2540.              (or charset default-mime-charset))
  2541.           )
  2542.         (let ((he
  2543.                (if (re-search-forward "^$" nil t)
  2544.                (match-end 0)
  2545.              (point-min)
  2546.              )))
  2547.           (if (= (point-min) 1)
  2548.               (progn
  2549.             (goto-char he)
  2550.             (insert
  2551.              (concat "\n"
  2552.                  (mime-create-tag
  2553.                   (concat type "/" stype pstr) encoding)))
  2554.             )
  2555.             (delete-region (point-min) he)
  2556.             (insert
  2557.              (mime-create-tag
  2558.               (concat type "/" stype pstr) encoding))
  2559.             ))
  2560.         ))))
  2561.     (if code-conversion
  2562.         (decode-mime-charset-region (point-min) (point-max)
  2563.                     default-mime-charset)
  2564.       )
  2565.     ))))
  2566.  
  2567. (defun mime/edit-again (&optional code-conversion no-separator no-mode)
  2568.   (interactive)
  2569.   (mime-editor::edit-again code-conversion)
  2570.   (goto-char (point-min))
  2571.   (save-restriction
  2572.     (narrow-to-region
  2573.      (point-min)
  2574.      (if (re-search-forward
  2575.       (concat "^\\(" (regexp-quote mail-header-separator) "\\)?$")
  2576.       nil t)
  2577.      (match-end 0)
  2578.        (point-max)
  2579.        ))
  2580.     (goto-char (point-min))
  2581.     (while (re-search-forward
  2582.         "^\\(Content-.*\\|Mime-Version\\):" nil t)
  2583.       (delete-region (match-beginning 0) (1+ (std11-field-end)))
  2584.       ))
  2585.   (or no-separator
  2586.       (and (re-search-forward "^$")
  2587.        (replace-match mail-header-separator)
  2588.        ))
  2589.   (or no-mode
  2590.       (mime/editor-mode)
  2591.       ))
  2592.  
  2593.  
  2594. ;;; @ end
  2595. ;;;
  2596.  
  2597. (provide 'tm-edit)
  2598.  
  2599. (run-hooks 'tm-edit-load-hook)
  2600.  
  2601. ;;; tm-edit.el ends here
  2602.